我知道inspect.getargspec可以用来获取函数参数的名称:
>>> from inspect import getargspec
>>> def foo1(a, b):
... pass
...
>>> getargspec(foo1).args
['a', 'b']
Run Code Online (Sandbox Code Playgroud)
但以下并不是我所期望的:
>>> class X(object):
... def foo2(self, a, b):
... pass
...
>>> x = X()
>>> getargspec(x.foo2).args
['self', 'a', 'b']
Run Code Online (Sandbox Code Playgroud)
并且:
>>> from functools import partial
>>> def foo3(a, b, c):
... pass
...
>>> foo4 = partial(foo3, c=1)
>>> getargspec(foo4).args
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "C:\Python27\lib\inspect.py", line 816, in getargspec
raise TypeError('{!r} is not a Python function'.format(func))
TypeError: <functools.partial object at 0x000000000262F598> is not a Python function
Run Code Online (Sandbox Code Playgroud)
我怎样才能使foo1,x.foo2全部foo4回归['a', 'b']?
partial()对象不是函数。它们的默认参数以及原始可调用对象存储为单独的属性。反省那些:
>>> from functools import partial
>>> def foo3(a, b, c):
... pass
...
>>> foo4 = partial(foo3, c=1)
>>> foo4.args, foo4.keywords
((), {'c': 1})
>>> from inspect import getargspec
>>> getargspec(foo4.func)
ArgSpec(args=['a', 'b', 'c'], varargs=None, keywords=None, defaults=None)
Run Code Online (Sandbox Code Playgroud)
方法是作为第一个参数传入实例的函数的薄包装。实际的函数不会更改签名,唯一改变的是第一个参数是自动为您传递的。
要构建“通用”解决方案,您必须测试所拥有的对象的类型,以解包方法或部分和特殊情况:
def generic_get_args(callable):
if {'args', 'keywords', 'func'}.issubset(dir(callable)):
# assume a partial object
spec = getargspec(callable.func).args[len(callable.args):]
return [var for var in spec if var not in callable.keywords]
if getattr(callable, '__self__', None) is not None:
# bound method
return getargspec(callable).args[1:]
return getargspec(callable).args
Run Code Online (Sandbox Code Playgroud)
针对您的foo1,X().foo2和进行演示foo4:
>>> generic_get_args(foo1)
['a', 'b']
>>> generic_get_args(X().foo2)
['a', 'b']
>>> generic_get_args(foo4)
['a', 'b']
Run Code Online (Sandbox Code Playgroud)