如何获取可调用的签名参数,或者可靠地确定何时不可以?

Lau*_*ves 8 python python-3.x

内置int有两个参数:

>>> print(int.__doc__)
int(x=0) -> integer
int(x, base=10) -> integer

Convert a number or string to an integer, or return 0 if no arguments
...
Run Code Online (Sandbox Code Playgroud)

但是,(在CPython 3.4.0中)inspect.signature显示0:

>>> len(inspect.signature(int).parameters)
0
Run Code Online (Sandbox Code Playgroud)

与用户定义的功能相反:

>>> def my_int(x, base=10):
...     return int(x, base)
... 
>>> len(inspect.signature(my_int).parameters)
2
Run Code Online (Sandbox Code Playgroud)

对文档inspect.signature不这样说:

在某些Python实现中,某些可调用内容可能无法内省.例如,在CPython中,C中定义的一些内置函数不提供有关其参数的元数据.

但他们也说:

如果不能提供签名,则引发ValueError;如果不支持该类型的对象,则引发TypeError.

所以我很惊讶,我没有得到一个ValueError,而是得到了一个看起来不正确的签名.

有没有办法可靠地(并以编程方式)确定何时无法获得可调用的参数inspect?也就是说,如果我得到类似的东西int,有没有办法区分"这个东西没有任何参数"和"不可能确定这个东西有什么参数"?

1.6*_*618 3

有一个开放的错误报告: http://bugs.python.org/issue23934

问题是,如果传递给的 objsignature()是“类型”,并且它没有用户定义的initnew,它只会放弃并返回object具有 0 个参数的签名。

如果 obj 位于内置模块中,并且它是一个“类型”,但不是异常,那么它很可能无法与signature().

我想出了这个解决方法来查找问题对象...它不是特别优雅,但可能对您有用:

def count_params():
    output = {}
    for funcname in dir(builtins):
        f = getattr( builtins,funcname)
        if isinstance(f, type):
            try:
                paramcount = len(inspect.signature(f).parameters)
                output[funcname] = paramcount
            except:
                pass
                #print("%s is a %s" % (funcname, type(f)))
    return output
Run Code Online (Sandbox Code Playgroud)

输出:

{'__loader__': 0,
 'bool': 0,
 'bytes': 0,
 'complex': 0,
 'enumerate': 0,
 'filter': 0,
 'float': 0,
 'frozenset': 0,
 'int': 0,
 'map': 0,
 'memoryview': 0,
 'object': 0,
 'range': 0,
 'reversed': 0,
 'slice': 0,
 'str': 0,
 'tuple': 0,
 'zip': 0}
Run Code Online (Sandbox Code Playgroud)