【问题标题】:Python's inspect.Signature's signature seems to violate python's signatures rulesPython inspect.Signature 签名似乎违反了 python 的签名规则
【发布时间】:2019-08-01 12:42:45
【问题描述】:

inspect 模块是如何使其看起来像一个没有默认值的参数(尽管它有),这样做的原因是什么(如果有的话)?

inspect.Signature 的帮助显示 return_annotation 参数没有默认值:

>>> import inspect
>>> help(inspect.Signature)
(...)
class Signature(builtins.object)
 |  Signature(parameters=None, *, return_annotation, __validate_parameters__=True)
(...)

然而,人们可以只用一个参数构造一个签名:

>>> sig = inspect.Signature(None)
>>> # Nothing bad happens

这似乎违反了规则。所以查看Signature 类的代码,我看到了:

def __init__(self, parameters=None, *, return_annotation=_empty, __validate_parameters__=True)

好吧,return_annotation 毕竟确实有一个默认值(这就是inspect.Signature(None) 起作用的原因)。

所以问题是:

inspect 模块是如何实现这个诡计的? 这样做有好的理由吗?

【问题讨论】:

    标签: python python-internals


    【解决方案1】:

    显然,help 在后台调用inspect.signature(object),其中object 是函数。这会将inspect.Signature.empty 默认参数处理为显示 根本没有默认值。

    另一个例子:

    >>> def thing(self, a=inspect.Signature.empty):
    ...     ...
    ... 
    >>> help(thing)
    Help on function thing in module __main__:
    
    thing(self, a)  # Here it is!
    

    您可以通过运行以下命令查看 help 函数的幕后功能:

    import trace
    trace.Trace().runfunc(help, thing)
    

    对我来说(Python 3.6)它显示了这个:

    <snip>
    pydoc.py(1357):             try:
    pydoc.py(1358):                 signature = inspect.signature(object)
     --- modulename: inspect, funcname: signature
    inspect.py(3002):     return Signature.from_callable(obj, follow_wrapped=follow_wrapped)
     --- modulename: inspect, funcname: from_callable
    inspect.py(2751):         return _signature_from_callable(obj, sigcls=cls,
    <snip>
    pydoc.py(1361):             if signature:
    pydoc.py(1362):                 argspec = str(signature)
    

    如果你在你的代码中复制这个,你会得到这个:

    >>> inspect.signature(thing)
    <Signature (self, a)>
    >>> str(_)
    '(self, a)'  # huh?!
    

    【讨论】:

    • 感谢@ForceBru。据我所知,它与inspect._emptyinspect.Signature.empty 指向,但看不到如何 _empty 类型在帮助中将自己声明为“不可见”)有关,或为什么会这样做。
    • 它只是将参数标记为没有默认值。如果您要以不同的方式实现inspect.Signature,您可以选择此类参数的不同表示,所以这并不是真正的“诡计”,它更多的是实现细节。
    猜你喜欢
    • 1970-01-01
    • 2020-04-11
    • 2015-01-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多