Getting method parameter names in Python
给定的Python功能: </P >
1 2 | def aMethod(arg1, arg2): pass |
我怎么能提取的数量和名称的论点。例如,有一个是在给定的参考函数,该函数在想什么。[返回](arg1,arg2")。 </P >
使用的场景,这是在冰上有一个decorator,我希望到用同样的方法输入命令的论点,那是他们的实际appear功能作为一个密钥。例如,你会看的是《decorator印制的"A、B"当呼叫amethod("A"、"B")? </P >
看看inspect模块-这将为您检查各种代码对象属性。
1 2 | >>> inspect.getfullargspec(aMethod) (['arg1', 'arg2'], None, None, None) |
其他结果是*args和**kwargs变量的名称,以及提供的默认值。IE.
1 2 3 | >>> def foo(a,b,c=4, *arglist, **keywords): pass >>> inspect.getfullargspec(foo) (['a', 'b', 'c'], 'arglist', 'keywords', (4,)) |
请注意,在某些Python实现中,某些可调用文件可能不是可内省的。例如,在cpython中,C中定义的一些内置函数没有提供关于其参数的元数据。因此,在使用具有内置功能的
由于python 3.3,您还可以使用inspect.signature()来了解可调用对象的调用签名:
1 2 | >>> inspect.signature(foo) <Signature (a, b, c=4, *arglist, **keywords)> |
在cpython中,参数的数目是
1 | aMethod.func_code.co_argcount |
他们的名字在
1 | aMethod.func_code.co_varnames |
这些是cpython的实现细节,因此这可能在其他的Python实现中不起作用,比如Ironpython和Jython。
允许"传递"参数的一种可移植方法是使用签名
在decorator方法中,可以按以下方式列出原始方法的参数:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | 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) |
如果
1 2 3 4 5 | 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() |
例子:
1 2 3 4 5 6 7 8 9 10 | @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] |
我想这是你想要的东西,用一个装饰工。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | 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") |
运行它,它将产生以下输出:
1 2 3 4 | 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. |
我想你要找的是当地人的方法-
1 2 3 4 5 | In [6]: def test(a, b):print locals() ...: In [7]: test(1,2) {'a': 1, 'b': 2} |
Python 3.5 +:
DeprecationWarning: inspect.getargspec() is deprecated, use inspect.signature() instead
所以以前:
1 | func_args = inspect.getargspec(function).args |
现在:
1 | func_args = list(inspect.signature(function).parameters.keys()) |
测试:
1 | 'arg' in list(inspect.signature(function).parameters.keys()) |
假设我们有一个函数"function",它接受参数"arg",那么这个函数的值将为true,否则为false。
来自python控制台的示例:
1 2 3 4 | 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 |
python 3版本是:
1 2 3 | def _get_args_dict(fn, args, kwargs): args_names = fn.__code__.co_varnames[:fn.__code__.co_argcount] return {**dict(zip(args_names, args)), **kwargs} |
方法返回同时包含args和kwargs的字典。
在python 3.+中,使用签名的
例如,这里有一个用于打印这样的地图的装饰器:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | import inspect def decorator(f): def wrapper(*args, **kwargs): bound_args = inspect.signature(f).bind(*args, **kwargs) bound_args.apply_defaults() print(dict(bound_args.arguments)) return f(*args, **kwargs) return wrapper @decorator def foo(x, y, param_with_default="bars", **kwargs): pass foo(1, 2, extra="baz") # This will print: {'kwargs': {'extra': 'baz'}, 'param_with_default': 'bars', 'y': 2, 'x': 1} |
返回参数名称的列表,处理部分和正则函数:
1 2 3 4 5 | def get_func_args(f): if hasattr(f, 'args'): return f.args else: return list(inspect.signature(f).parameters) |
布莱恩回答的更新:
如果python 3中的函数只有关键字参数,则需要使用
1 2 3 | def yay(a, b=10, *, c=20, d=30): pass inspect.getfullargspec(yay) |
得出这样的结论:
1 | FullArgSpec(args=['a', 'b'], varargs=None, varkw=None, defaults=(10,), kwonlyargs=['c', 'd'], kwonlydefaults={'c': 20, 'd': 30}, annotations={}) |
为了更新一点Brian的答案,现在有一个很好的
1 2 3 4 5 6 7 8 9 10 | try: # python 3.3+ from inspect import signature except ImportError: from funcsigs import signature def aMethod(arg1, arg2): pass sig = signature(aMethod) print(sig) |
为了好玩,如果你想玩
在python 3中,下面是将
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | 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 |
那么现在的
似乎做的正是被要求的超级简单…
必须从函数范围内调用。
但是要注意,它将返回所有局部变量,因此如果需要,请确保在函数的最开始就返回。
同样要注意的是,正如注释中指出的,这不允许从范围之外进行。所以不完全是操作场景,但仍然匹配问题标题。所以我的回答。