inspect.signature 与 类 究竟如何协同工作?
How exactly does inspect.signature work with classes?
inspect.signature
文档声明它支持 类 作为输入,但没有涉及任何细节:
Accepts a wide range of Python callables, from plain functions and classes to functools.partial()
objects.
如果我调用 inspect.signature(MyClass)
,它的签名是什么 return? return MyClass.__init__
的签名吗?还是MyClass.__new__
?或者别的什么?
它几乎尽其所能地尝试一切。我认为细节可能是故意未记录的,因为它们很复杂并且可能会变得更多,因为新的 Python 版本添加了更多的东西来尝试。
例如,从 CPython 3.7.3 开始,code path 按顺序尝试以下操作:
- 如果 metaclass 在 Python 中定义了自定义
__call__
,它使用带有第一个参数的 metaclass __call__
的签名已删除。
- 否则,如果 class 具有 Python 中定义的
__new__
方法,它会使用删除第一个参数的 __new__
签名。
- 否则,如果 class 具有 Python 中定义的
__init__
方法,它会使用删除第一个参数的 __init__
签名。
- 否则,它遍历 MRO 寻找
__text_signature__
。如果找到,它会解析 __text_signature__
以获取签名信息。
- 如果仍然没有找到任何东西,如果类型的
__init__
是 object.__init__
并且类型的 __new__
是 object.__new__
,它 returns object
class 的签名。 (在这一点上有一个误导性的评论和一个可能涉及 metaclasses 的错误 - 评论说它将检查 type.__init__
,但它并没有这样做。我认为 this commit可能这里弄错了。)
- 如果它仍然没有找到任何东西,它会放弃并提出一个
ValueError
说它找不到任何东西。
inspect.signature
文档声明它支持 类 作为输入,但没有涉及任何细节:
Accepts a wide range of Python callables, from plain functions and classes to
functools.partial()
objects.
如果我调用 inspect.signature(MyClass)
,它的签名是什么 return? return MyClass.__init__
的签名吗?还是MyClass.__new__
?或者别的什么?
它几乎尽其所能地尝试一切。我认为细节可能是故意未记录的,因为它们很复杂并且可能会变得更多,因为新的 Python 版本添加了更多的东西来尝试。
例如,从 CPython 3.7.3 开始,code path 按顺序尝试以下操作:
- 如果 metaclass 在 Python 中定义了自定义
__call__
,它使用带有第一个参数的 metaclass__call__
的签名已删除。 - 否则,如果 class 具有 Python 中定义的
__new__
方法,它会使用删除第一个参数的__new__
签名。 - 否则,如果 class 具有 Python 中定义的
__init__
方法,它会使用删除第一个参数的__init__
签名。 - 否则,它遍历 MRO 寻找
__text_signature__
。如果找到,它会解析__text_signature__
以获取签名信息。 - 如果仍然没有找到任何东西,如果类型的
__init__
是object.__init__
并且类型的__new__
是object.__new__
,它 returnsobject
class 的签名。 (在这一点上有一个误导性的评论和一个可能涉及 metaclasses 的错误 - 评论说它将检查type.__init__
,但它并没有这样做。我认为 this commit可能这里弄错了。) - 如果它仍然没有找到任何东西,它会放弃并提出一个
ValueError
说它找不到任何东西。