我试图了解字节码的工作原理。
a.func() 是一个函数调用。对应的字节码大致是 LOAD_GLOBAL aLOAD_ATTR attrCALL_FUNCTION ,参数为 0。

如果 a 是一个模块,这完全没问题。但是如果 a 是一个对象,它必须传递对象实例本身。由于 Python 在编译时无法知道 a 是模块还是对象,因此无论 a 的类型如何,字节码自然是相同的。但是如果 self 是一个对象,运行时系统如何将 func 作为 a 的第一个参数处理?字节码级别以下是否有一些特殊处理,表示“如果在对象上调用它,则将对象作为第一个参数”?

最佳答案

字节码不必因不同的对象类型而变化。管理绑定(bind)行为是对象类型本身的责任。这在 descriptor protocol 中有介绍。

简而言之,LOAD_ATTR 通过 object.__getattribute__ hook 委托(delegate)对对象的属性访问:



对于模块,__getattribute__ 只是在 __dict__ 命名空间中查找名称并返回它。但是对于类和元类,如果属性支持,则实现将调用描述符协议(protocol)。函数支持描述符协议(protocol)并在被询问时返回绑定(bind)方法:

>>> class Foo:
...     def method(self): pass
...
>>> Foo().method  # access on an instance -> binding behaviour
<bound method Foo.method of <__main__.Foo object at 0x107155828>>
>>> Foo.method    # access on the class, functions just return self when bound here
<function Foo.method at 0x1073702f0>
>>> Foo.method.__get__(Foo(), Foo)  # manually bind the function
<bound method Foo.method of <__main__.Foo object at 0x107166da0>>

这种绑定(bind)行为也是 property classmethod staticmethod 对象如何工作的基础(后者通过返回函数本身来中和函数的绑定(bind)行为)。

关于Python字节码函数调用传递自我,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/45074917/

10-12 16:48