如何获取方法参数名称?

问题描述 投票:222回答:15

给出Python函数:

def a_method(arg1, arg2):
    pass

如何提取参数的数量和名称。即,考虑到我对func的引用,我希望func.[something]返回("arg1", "arg2")

此使用场景是我有一个装饰器,并且我希望以与实际函数作为键一样的顺序使用方法参数。即,当我调用"a,b"时,装饰器看起来像打印了a_method("a", "b")吗?

python decorator introspection python-datamodel
15个回答
337
投票

[看一下inspect模块-这将为您检查各种代码对象属性。

inspect

其他结果是* args和** kwargs变量的名称,以及提供的默认值。即

>>> inspect.getfullargspec(a_method)
(['arg1', 'arg2'], None, None, None)

请注意,在某些Python实现中,某些可调用对象可能不是自省的。例如,在CPython中,C中定义的某些内置函数不提供有关其参数的元数据。结果,如果在内置函数上使用>>> def foo(a, b, c=4, *arglist, **keywords): pass >>> inspect.getfullargspec(foo) (['a', 'b', 'c'], 'arglist', 'keywords', (4,)) ,则将获得ValueError

从Python 3.3开始,您可以使用inspect.getfullargspec()查看可调用对象的调用签名:

inspect.signature()

2
投票

[C0的更新:


2
投票

在python 3中,以下是将inspect.getfullargspecdef yay(a, b=10, *, c=20, d=30): pass inspect.getfullargspec(yay) 变成FullArgSpec(args=['a', 'b'], varargs=None, varkw=None, defaults=(10,), kwonlyargs=['c', 'd'], kwonlydefaults={'c': 20, 'd': 30}, annotations={}) (对于python <3.6使用*args来维持**kwargs的顺序):


2
投票

这里是不使用任何模块而获得功能参数的另一种方法。


0
投票

要更新一点from functools import wraps def display_param(func): @wraps(func) def wrapper(*args, **kwargs): param = inspect.signature(func).parameters all_param = { k: args[n] if n < len(args) else v.default for n, (k, v) in enumerate(param.items()) if k != 'kwargs' } all_param .update(kwargs) print(all_param) return func(**all_param) return wrapper ,现在有一个不错的def get_parameters(func): keys = func.__code__.co_varnames[:func.__code__.co_argcount][::-1] sorter = {j: i for i, j in enumerate(keys[::-1])} values = func.__defaults__[::-1] kwargs = {i: j for i, j in zip(keys, values)} sorted_args = tuple( sorted([i for i in keys if i not in kwargs], key=sorter.get) ) sorted_kwargs = {} for i in sorted(kwargs.keys(), key=sorter.get): sorted_kwargs[i] = kwargs[i] return sorted_args, sorted_kwargs def f(a, b, c="hello", d="world"): var = a print(get_parameters(f)) 反向端口,可以在较旧的python版本中使用:(('a', 'b'), {'c': 'hello', 'd': 'world'}) 。所以我个人的喜好会去


0
投票

funcsigs非常慢。最快的方法是


-2
投票

现在Signaturemakefun呢?


98
投票

在CPython中,参数数为

inspect.signature()

和它们的名字在开头

>>> inspect.signature(foo)
<Signature (a, b, c=4, *arglist, **keywords)>

这些是CPython的实现细节,因此这可能不适用于其他Python实现,例如IronPython和Jython。

一种接受“传递”参数的可移植方法是使用签名a_method.func_code.co_argcount 定义函数。这在例如a_method.func_code.co_varnames ,外部API层将大量关键字参数传递给较低级别​​的API。


22
投票

在装饰方法中,您可以通过以下方式列出原始方法的参数:

func(*args, **kwargs)

如果matplotlib对您来说很重要,那会有点复杂:

import inspect, itertools 

def my_decorator():

        def decorator(f):

            def wrapper(*args, **kwargs):

                # if you want arguments names as a list:
                args_name = inspect.getargspec(f)[0]
                print(args_name)

                # if you want names and values as a dictionary:
                args_dict = dict(itertools.izip(args_name, args))
                print(args_dict)

                # if you want values as a list:
                args_values = args_dict.values()
                print(args_values)

示例:

**kwargs

15
投票

我认为您正在寻找的是locals方法-

        def wrapper(*args, **kwargs):

            args_name = list(OrderedDict.fromkeys(inspect.getargspec(f)[0] + kwargs.keys()))
            args_dict = OrderedDict(list(itertools.izip(args_name, args)) + list(kwargs.iteritems()))
            args_values = args_dict.values()

13
投票

我认为这是某种可以使用装饰器满足您需要的东西。

@my_decorator()
def my_function(x, y, z=3):
    pass


my_function(1, y=2, z=3, w=0)
# prints:
# ['x', 'y', 'z', 'w']
# {'y': 2, 'x': 1, 'z': 3, 'w': 0}
# [1, 2, 3, 0]

运行它,将产生以下输出:


In [6]: def test(a, b):print locals()
   ...: 

In [7]: test(1,2)              
{'a': 1, 'b': 2}

11
投票

Python 3版本是:

class LogWrappedFunction(object):
    def __init__(self, function):
        self.function = function

    def logAndCall(self, *arguments, **namedArguments):
        print "Calling %s with arguments %s and named arguments %s" %\
                      (self.function.func_name, arguments, namedArguments)
        self.function.__call__(*arguments, **namedArguments)

def logwrap(function):
    return LogWrappedFunction(function).logAndCall

@logwrap
def doSomething(spam, eggs, foo, bar):
    print "Doing something totally awesome with %s and %s." % (spam, eggs)


doSomething("beans","rice", foo="wiggity", bar="wack")

该方法返回一个既包含参数又包含参数的字典。


10
投票

Python 3.5 +:

[DeprecationWarning:不建议使用inspect.getargspec(),请改用inspect.signature()] >>

之前是:

C:\scripts>python decoratorExample.py
Calling doSomething with arguments ('beans', 'rice') and named arguments {'foo':
 'wiggity', 'bar': 'wack'}
Doing something totally awesome with beans and rice.

现在:

def _get_args_dict(fn, args, kwargs):
    args_names = fn.__code__.co_varnames[:fn.__code__.co_argcount]
    return {**dict(zip(args_names, args)), **kwargs}

要测试:

func_args = inspect.getargspec(function).args

考虑到我们有函数'function'接受了参数'arg',它将被评估为True,否则为False。

Python控制台中的示例:

func_args = list(inspect.signature(function).parameters.keys())

6
投票

在Python 3. +中,带有'arg' in list(inspect.signature(function).parameters.keys()) 对象的一种简单方法是使用签名的Python 3.6.0 (v3.6.0:41df79263a11, Dec 23 2016, 07:18:10) [MSC v.1900 32 bit (Intel)] on win32 >>> import inspect >>> 'iterable' in list(inspect.signature(sum).parameters.keys()) True 方法来获取参数名称与值之间的映射!


2
投票

返回参数名称列表,处理部分函数和常规函数:

© www.soinside.com 2019 - 2024. All rights reserved.