Python 真的为每个新实例创建所有绑定方法吗?
Does Python really create all bound method for every new instance?
我正在阅读 Python (3.4) 中的 classes,据我了解,似乎每个新对象都有自己的绑定方法实例。
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
作为 class 实例将被传递。
我认为这可能无法用语言轻松实现。
每个新实例是否还包含其绑定方法的新实例?
如果是这样,这不会损害性能,或者比在 Java 中的对象中使用 "shared" 方法的其他语言更谨慎地创建新对象吗?
方法绑定按需,每次访问一个。
访问函数的名称会调用 descriptor protocol,它在函数对象上 returns 是一个绑定方法。
绑定方法是函数对象的薄包装;它存储对原始函数和实例的引用。当调用方法对象时,它依次将调用传递给函数,并将实例作为第一个参数插入。
创建实例时不会创建方法,因此不需要先验的额外内存。
您可以手动重新创建步骤:
>>> 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
此架构还使 classmethod
, staticmethod
, and property
对象工作。您可以创建自己的描述符,创建大量有趣的绑定行为。
揭秘检查器我做了展示,函数保存在主 class A
字典中并在实例之间共享。但是最后几行显示一旦我们将方法绑定到唯一的内存地址上。
class A:
def __init__(self, name):
self.name = name
def foo(self):
print(self.name)
a = A('One')
b = A('Two')
d=a.__dict__
D=A.__dict__
print('dict a:', d)
print('dict A:', D)
print(D['foo']) #<function A.foo at 0x000001AF4258CC80>
# both next __func__ point to the parent dict
print(a.foo.__func__) #<function A.foo at 0x000001AF4258CC80>
print(b.foo.__func__) #<function A.foo at 0x000001AF4258CC80>
print(a.foo)
print(b.foo)
#already bound on unique address
print(a.foo==b.foo)
完整输出:
dict a: {'name': 'One'}
dict A: {'__module__': '__main__', '__init__': <function A.__init__ at 0x000001AF425D3730>, 'foo': <function A.foo at 0x000001AF425D3620>, '__dict__': <attribute '__dict__' of 'A' objects>, '__weakref__': <attribute '__weakref__' of 'A' objects>, '__doc__': None}
<function A.foo at 0x000001AF425D3620>
<function A.foo at 0x000001AF425D3620>
<function A.foo at 0x000001AF425D3620>
<bound method A.foo of <__main__.A object at 0x000001AF425E21D0>>
<bound method A.foo of <__main__.A object at 0x000001AF42375C50>>
False
我正在阅读 Python (3.4) 中的 classes,据我了解,似乎每个新对象都有自己的绑定方法实例。
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
作为 class 实例将被传递。
我认为这可能无法用语言轻松实现。
每个新实例是否还包含其绑定方法的新实例?
如果是这样,这不会损害性能,或者比在 Java 中的对象中使用 "shared" 方法的其他语言更谨慎地创建新对象吗?
方法绑定按需,每次访问一个。
访问函数的名称会调用 descriptor protocol,它在函数对象上 returns 是一个绑定方法。
绑定方法是函数对象的薄包装;它存储对原始函数和实例的引用。当调用方法对象时,它依次将调用传递给函数,并将实例作为第一个参数插入。
创建实例时不会创建方法,因此不需要先验的额外内存。
您可以手动重新创建步骤:
>>> 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
此架构还使 classmethod
, staticmethod
, and property
对象工作。您可以创建自己的描述符,创建大量有趣的绑定行为。
揭秘检查器我做了展示,函数保存在主 class A
字典中并在实例之间共享。但是最后几行显示一旦我们将方法绑定到唯一的内存地址上。
class A:
def __init__(self, name):
self.name = name
def foo(self):
print(self.name)
a = A('One')
b = A('Two')
d=a.__dict__
D=A.__dict__
print('dict a:', d)
print('dict A:', D)
print(D['foo']) #<function A.foo at 0x000001AF4258CC80>
# both next __func__ point to the parent dict
print(a.foo.__func__) #<function A.foo at 0x000001AF4258CC80>
print(b.foo.__func__) #<function A.foo at 0x000001AF4258CC80>
print(a.foo)
print(b.foo)
#already bound on unique address
print(a.foo==b.foo)
完整输出:
dict a: {'name': 'One'}
dict A: {'__module__': '__main__', '__init__': <function A.__init__ at 0x000001AF425D3730>, 'foo': <function A.foo at 0x000001AF425D3620>, '__dict__': <attribute '__dict__' of 'A' objects>, '__weakref__': <attribute '__weakref__' of 'A' objects>, '__doc__': None}
<function A.foo at 0x000001AF425D3620>
<function A.foo at 0x000001AF425D3620>
<function A.foo at 0x000001AF425D3620>
<bound method A.foo of <__main__.A object at 0x000001AF425E21D0>>
<bound method A.foo of <__main__.A object at 0x000001AF42375C50>>
False