繁体   English   中英

函数调用和__call__属性

[英]Function call and the __call__ attribute

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

但是碰巧函数确实具有__call__方法。 因此, __call__方法也具有__call__方法。 以下REPL会话显示我们可以链接__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__属性是在类型上定义的描述符对象 ,绑定到您在其中查找的对象:

>>> 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>

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

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

printbuiltin_function_or_method类的一个实例:

>>> type(print)
builtin_function_or_method

众所周知(希望如此),当您访问方法时,实例作为第一个参数隐式传递:

>>> type(print).__call__(print, 10)
10
>>> print.__call__(10)  # equivalent
10

这意味着,当您访问函数的__call__时,您实际上具有绑定方法之类的东西。 但是,绑定方法(或在这种情况下为methodwrappers)也是method_wrapper类型的method_wrapper

>>> type(print.__call__)
method-wrapper

因此,当您访问该方法的__call__方法时,它还是一个“新”绑定方法。

>>> type(print.__call__).__call__(print.__call__, 10)  # equivalent
10

在这一点上,它变得递归,因为方法包装器的方法只是另一个方法包装器实例:

>>> type(print.__call__.__call__)
method-wrapper

但是,所有这些操作只会创建许多“不必要的”绑定方法...

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM