I am reading about classes in Python (3.4) and from what I understand it seems that every new object has its own bound methods instances.
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)
The output of this is False
.
This seems to me as a waste of memory. I thought that internally a.foo
and b.foo
would point somehow internally to one function in memory: A.foo
where self
as the class instance will be passed.
I assume this maybe cannot be implemented easily in the language.
Does each new instance contain also new instances of its bound methods?
If so, does not this hurt the performance or make case for creating new objects more cautiously than in other languages where methods are "shared" among objects like in Java?
Methods are bound on demand, each time you access one.
Accessing the name of a function invokes the descriptor protocol, which on function objects returns a bound method.
A bound method is a thin wrapper around a function object; it stores a reference to the original function and to the instance. When calling a method object, it in turn passes the call to the function, with instance inserted as a first argument.
Methods are not created when the instance is created, so there is no extra memory required a-priori.
You can re-create the steps manually:
>>> 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
It is only the method object that is recreated each time; the underlying function remains stable:
>>> a.foo is a.foo
False
>>> b = A('Two')
>>> b.foo is a.foo
False
>>> b.foo.__func__ is a.foo.__func__
True
This architecture also makes classmethod
, staticmethod
, and property
objects work. You can create your own descriptors, creating a whole host of interesting binding behaviours.