2015-05-21 26 views
5

我正在阅读有关Python(3.4)中的类,并从我的理解看来,每个新对象都有自己的绑定方法实例。Python是否真的为每个新实例创建所有绑定方法?

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.foob.foo会以某种方式内部指向内存中的一个函数:A.foo其中self作为类实例将被传递。

我认为这可能无法在语言中轻松实现。

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

如果是这样,那么这不会伤害到性能,或者比其他语言中的方法在诸如Java之类的对象“共享”时更谨慎地创建新对象?

+0

你能链接到你读过的东西吗? –

+0

@SotiriosDelimanolis'X().f == X.f'将导致'False'(其中f是instace方法)。这足以让人想那样。 –

+0

尽管每个绑定的方法引用了相同的底层函数。包装的内存开销很小。 – chepner

回答

14

方法绑定点播,每次访问一个。

访问函数的名称将调用descriptor protocol,函数对象返回一个绑定方法。

绑定方法是一个函数对象周围的薄包装器;它存储对原始函数和实例的引用。当调用方法对象时,它又将调用传递给该函数,并将实例插入为第一个参数。

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

可以手动重新创建步骤:

>>> 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对象。您可以创建自己的描述符,创建一系列有趣的绑定行为。

+0

这也是你的答案,所以你得到的代表显然不需要更多的任何方式; o) – jonrsharpe

+0

@jonrsharpe:哈,但是这个已经被接受了! :-P我没有完全重读这里的问题;回想起来,问题和答案都是完美的重复。我有一个印象,有更多的解释在另一篇文章。 –

相关问题