我有兴趣获得一种获取可调用Python对象所采用的参数和关键字参数列表的一般方法。对于具有inspect.getargspec
功能的函数,这是直截了当的,例如:
import inspect
from functools import partial
def foo(*args, **kwargs):
return args, kwargs
print(inspect.getargspec(foo))
>>ArgSpec(args=[], varargs='args', keywords='kwargs', defaults=None)
def bar(*args):
return args
print(inspect.getargspec(bar))
>>ArgSpec(args=[], varargs='args', keywords=None, defaults=None)
然而,在以下情况下会失败:
partial_function = partial(foo, kwarg="value")
inspect.getargspec(partial_function)
>>TypeError: <functools.partial object at 0x11748bc58> is not a Python function
class Foo(object):
def __call__(self, *args, **kwargs):
return args, kwargs
foo_instance = Foo()
inspect.getargspec(foo_instance)
>>TypeError: <__main__.Foo object at 0x116c13ed0> is not a Python function
inspect.getargspec(zip)
>>TypeError: <built-in function zip> is not a Python function
请注意,有一些方法可以获取部分函数和可调用对象的参数,即:
inspect.getargspec(partial_function.func)
>>ArgSpec(args=[], varargs='args', keywords='kwargs', defaults=None)
inspect.getargspec(foo_instance.__call__)
>>ArgSpec(args=['self'], varargs='args', keywords='kwargs', defaults=None)
但是如果可能的话,我想要一种更通用的方法来获得这些结果。
答案 0 :(得分:2)
所有这些都可以使用inspect.signature
辅助函数来处理,正如其文档中所述:
接受各种python callables,从普通函数和类到
functools.partial()
个对象。
signature
做了什么需要你的callable并从中构造一个Signature
对象:
>>> from inspect import signature
>>> s = signature(Foo()) # class as shown in your example
现在参数位于parameters
实例的Signature
映射属性中:
>>> s.parameters
mappingproxy({'args': <Parameter "*args">, 'kwargs': <Parameter "**kwargs">})
使用partial
对象,您将获得相应的表示:
>>> def foo(a, b, c): pass
>>> p = partial(foo, c = 30)
>>> signature(p).parameters
<Signature (a, b, *, c=20)>
对于zip
这样的内置函数,这并不总是可行的,其中一些函数没有公开适当的元数据来构造签名,from PEP 362
:
在某些Python实现中,某些函数可能无法内省。例如,在CPython中,
C
中定义的内置函数不提供有关其参数的元数据。添加对它们的支持超出了本PEP的范围。
因此,虽然zip
不是公开自身信息的类型,但其他类似于all
:
>>> signature(all)
<Signature (iterable, /)>
你很遗憾地要求try-except
这些,没有别的办法可以做。
signature
帮助程序处理的案例在引入它的implementation section of PEP 362
中进行了枚举。
一般来说,{3}已经在Python 3中暂时推荐inspect.getargspec
,建议的方法(如果你使用的是Python 3)就是使用Signature
个对象提供的表示。
如果在Python 2
上,我很确定你不能直接使用getargspec
,你应该使用getfullargspec
作为Anttis的回答建议。
答案 1 :(得分:0)
getfullargspec
也正确处理部分内容。它之前已被弃用但未初步,因为它被认为对单源Python 2/3多语言代码非常有用。
另一个选项是signature
,这有点复杂。