Reputation: 3
As below, id(a.__getattribute__)
return different value when __getattr__
method defined. How did this happened? (My Python is v3.7.0)
class A():
def __getattribute__(self,key):
print(key)
return super().__getattribute__(key)
def f():
pass
def __getattr__(self,key):
print(key)
return super().__getattr__(key)
a=A()
print('id(a.__getattribute__)')
print(id(a.__getattribute__))
print(id(a.__getattribute__))
print(id(a.__getattribute__))
print(id(a.__getattribute__))
Output results:
id(a.__getattribute__)
__getattribute__
44147656
__getattribute__
12643664
__getattribute__
44147656
__getattribute__
12643664
When comment __getattr__
:
...
## def __getattr__(self,key):
## print(key)
## return super().__getattr__(key)
...
Output results:
id(a.__getattribute__)
__getattribute__
11005264
__getattribute__
11005264
__getattribute__
11005264
__getattribute__
11005264
Upvotes: 0
Views: 60
Reputation: 104712
Whenever you do an instance.method
lookup, you'll always get a new bound method object. This binding is how the self
argument gets passed to the function (the lookup of the method binds the instance to a function that was in the class dictionary).
Whether you get a method with the same id
or not has to do with how Python computes those id
values. The values you get from id
are guaranteed to be unique, but only among objects that exist at the same time. After one object is garbage collected, another object with the same ID may be created.
CPython produces id
s based on the memory address of the object. The same memory will be often reused for different bound method objects at different times, since caching memory is much faster than always using new memory. Exactly when this reuse happens is an implementation detail. Other Python interpreters (like PyPy or Jython) and even other versions of CPython may do it differently or not at all. You should never rely upon the specific details of this behavior (or any other details of the specific values you get from id
). The only thing you should rely on id
for is that it will always be different for objects that exist simultaneously.
I suspect it is coincidence that changing the number of methods in your class changes the behavior of id
reuse. Perhaps there is a reason for it (e.g. something in the class machinery is creating one extra bound method object somewhere), but there is no possible benefit you can get from knowing the exact cause. The details are going to be very implementation specific, and so you should never rely upon them, as if you do, they may change and break your code without warning.
Upvotes: 1