python - 函数调用和 __call__ 属性

标签 python callable-object

Python 的可调用对象是具有 __call__ 方法的对象。 它们大部分时间是函数,但也可能是类实例。

但是函数确实有一个 __call__ 方法。 因此,一个 __call__ 方法也有一个 __call__ 方法。 以下 REPL session 表明我们可以链接 __call__:

>>> print
<built-in function print>

>>> print.__call__
<method-wrapper '__call__' of builtin_function_or_method object at 0x0000025E2D597F78>

>>> print.__call__.__call__
<method-wrapper '__call__' of method-wrapper object at 0x0000025E2F631438>

>>> print.__call__.__call__.__call__
<method-wrapper '__call__' of method-wrapper object at 0x0000025E2F5F85F8>

>>> print.__call__.__call__.__call__.__call__
<method-wrapper '__call__' of method-wrapper object at 0x0000025E2F725DA0> 

...等等。 值得注意的是,所有这些方法都有不同的地址。 此外,它们都具有相同的行为:

>>> print("a")
a
>>> print.__call__("a")
a
>>> print.__call__.__call__("a")
a
>>> print.__call__.__call__.__call__("a")

那么,当我写 print("a") 时,实际上调用的是什么? 是 print 还是 print.__call__? 如果我用 __call__ 方法定义一个 Foo 类呢?

此外,每个 __call__ 方法怎么可能有自己的不同 __call__ 方法? 难道它们实际上是在我尝试访问它们时创建的吗?

最佳答案

与类的方法一样,__call__ 属性是一个 descriptor object在类型上定义,绑定(bind)到您查找它的对象:

>>> type(print).__dict__['__call__']
<slot wrapper '__call__' of 'builtin_function_or_method' objects>
>>> type(print).__dict__['__call__'].__get__(print)
<method-wrapper '__call__' of builtin_function_or_method object at 0x10cc66f78>
>>> print.__call__
<method-wrapper '__call__' of builtin_function_or_method object at 0x10cc66f78>

绑定(bind)行为(通过 __get__ 方法)是生成的 method-wrapper 实例如何知道将 print 对象作为 self,就像实例被传递到您在自定义 Python 类上定义的方法中一样。

是的,这意味着它们是按需创建的,因此将具有唯一的 ID。它们只是同一类型的更多实例。

关于python - 函数调用和 __call__ 属性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46159984/

相关文章:

python - 向 shopify 域(python)发出请求会引发 SSLError

python - 如何解析 AND/OR 运算符以评估 python 中的条件字符串

python - 使用 pip 和 virtualenv 在 Windows 上安装 psycopg2 时出错

julia - 如何确定 Julia 对象是否可调用

c++ - STL 概念是否涵盖了 STL 算法的所有参数要求?

c++ - 如何检查模板参数是否是具有给定签名的可调用对象

python - 获取QListView中选定的项目

python - 装饰器 "object is not callable"

python2.5多处理池