假设函数a_method的定义如下
def a_method(arg1, arg2):
pass
从a_method本身开始,我怎么能得到参数名-例如,作为字符串的元组,如("arg1", "arg2")?
假设函数a_method的定义如下
def a_method(arg1, arg2):
pass
从a_method本身开始,我怎么能得到参数名-例如,作为字符串的元组,如("arg1", "arg2")?
当前回答
操作一些函数的参数名称的最简单方法:
parameters_list = list(inspect.signature(self.YOUR_FUNCTION).parameters))
结果:
['YOUR_FUNCTION_parameter_name_0', 'YOUR_FUNCTION_parameter_name_1', ...]
这样做会更容易,因为你得到了具体的一个:
parameters_list = list(inspect.signature(self.YOUR_FUNCTION).parameters)[0]
结果:
'YOUR_FUNCTION_parameter_name_0'
其他回答
在CPython中,参数的数量是
a_method.func_code.co_argcount
他们的名字在开头
a_method.func_code.co_varnames
这些是CPython的实现细节,所以这可能不适用于Python的其他实现,比如IronPython和Jython。
承认“传递”参数的一种可移植方法是使用func(*args, **kwargs)签名来定义函数。这在matplotlib中被大量使用,其中外层API层将大量关键字参数传递给底层API。
我觉得你要找的是当地人的方法
In [6]: def test(a, b):print locals()
...:
In [7]: test(1,2)
{'a': 1, 'b': 2}
对于那些像我一样正在寻找将所有参数及其值(默认值或非默认值)放入一个字典的解决方案的人,我还有另一个建议。
import inspect
def get_arguments(func, args, kwargs, is_method=False):
offset = 1 if is_method else 0
specs = inspect.getfullargspec(func)
d = {}
for i, parameter in enumerate(specs.args[offset:]):
i += offset
if i < len(args):
d[parameter] = args[i]
elif parameter in kwargs:
d[parameter] = kwargs[parameter]
else:
d[parameter] = specs.defaults[i - len(args)]
return d
现在在这样的装饰器中打印get_arguments的返回值
def a_function_decorator(func):
def inner(*args, **kwargs):
print(get_arguments(func, args, kwargs))
return func(*args, **kwargs)
return inner
把它应用到一个函数上
@a_function_decorator
def foo(a, b, c="default_c", d="default_d"):
pass
会给我们
foo(1, 2, d="eek")
# {'a': 1, 'b': 2, 'c': 'default_c', 'd': 'eek'}
foo(1, 2, "blah")
# {'a': 1, 'b': 2, 'c': 'blah', 'd': 'default_c'}
foo(1, 2)
# {'a': 1, 'b': 2, 'c': 'default_c', 'd': 'default_d'}
方法也是一样
def a_method_decorator(func):
def inner(*args, **kwargs):
print(get_arguments(func, args, kwargs, is_method=True))
return func(*args, **kwargs)
return inner
class Bar:
@a_method_decorator
def foo(self, a, b, c="default_c", d="default_d"):
pass
Bar().foo(1, 2, d="eek")
#{'a': 1, 'b': 2, 'c': 'default_c', 'd': 'eek'}
Bar().foo(1, 2, "blah")
# {'a': 1, 'b': 2, 'c': 'blah', 'd': 'default_c'}
Bar().foo(1, 2)
# {'a': 1, 'b': 2, 'c': 'default_c', 'd': 'default_d'}
它当然不是最漂亮的解决方案,但它是我见过的第一个完全符合我要求的解决方案。
在python 3中,下面是将*args和**kwargs放入dict(对于python < 3.6使用OrderedDict来维护dict顺序):
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
Python 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的字典。