Python真的为每个新实例创建了所有绑定方法吗?


问题内容

我正在阅读有关Python(3.4)中的类的信息,据我了解,似乎每个新对象都有其自己的绑定方法实例。

class A:

    def __init__(self, name):
        self.name = name

    def foo(self):
        print(self.name)

a = A('One')
b = A('Two')

print(a.foo ==  b.foo)

此输出为False

在我看来,这是浪费记忆。我以为是内部的,a.foo并且b.foo会以某种方式在内部指向内存中的一个函数:类实例将在A.foo哪里self传递。

我认为这可能无法轻松实现。

每个新实例是否还包含其绑定方法的新实例?

如果是这样,这是否会比在其他语言(如Java)之间在对象之间“共享”方法的其他语言更加谨慎地创建新对象,就不会影响性能或使情况变得更谨慎吗?


问题答案:

每次访问一种方法时,方法都是 按需 绑定的。

访问函数名称将调用描述符协议,该协议在函数对象上返回绑定方法。

绑定方法是围绕功能对象的薄包装器。它存储了对原始函数和实例的引用。调用方法对象时,它依次将调用传递给函数,并插入实例作为第一个参数。

创建实例时不会创建方法,因此不需要先验的额外内存。

您可以手动重新创建步骤:

>>> class A:
...     def __init__(self, name):
...         self.name = name
...     def foo(self):
...         print(self.name)
... 
>>> a = A('One')
>>> a.foo
<bound method A.foo of <__main__.A object at 0x100a27978>>
>>> a.foo.__self__
<__main__.A object at 0x100a27978>
>>> a.foo.__func__
<function A.foo at 0x100a22598>
>>> A.__dict__['foo']
<function A.foo at 0x100a22598>
>>> A.__dict__['foo'].__get__(a, A)
<bound method A.foo of <__main__.A object at 0x100a27978>>
>>> A.__dict__['foo'].__get__(a, A)()
One

每次都只重新创建方法对象。基本功能保持稳定:

>>> a.foo is a.foo
False
>>> b = A('Two')
>>> b.foo is a.foo
False
>>> b.foo.__func__ is a.foo.__func__
True

这种架构也使得classmethodstaticmethodproperty对象。您可以创建自己的描述符,创建大量有趣的绑定行为。