The classmethod decorator wraps the method in a handle. MyClass.my_class_method does the same as the MyClass.__dict__['my_class_method'].__get__(None, MyClass) code MyClass.__dict__['my_class_method'].__get__(None, MyClass) ; __get__ returns a separate bound method for each call, so 2 are separate objects and is fails.
id is just a coincidence (common) , since id in CPython is calculated based on the address where the object is located; when the wrapper id first associated method is calculated, the reference count for this shell is reduced and the shell is freed; by chance, the second will be allocated to exactly one address. id(obj) guaranteed to be different only for every living object.
In Python 2, the first is true for unbound methods:
>>> class MyClass(): ... def x(self): ... pass ... >>> MyClass.x <unbound method MyClass.x> >>> MyClass.x is MyClass.x False
In Python 3, the semantics of unrelated methods have been changed, and now
>>> class MyClass(): ... def x(self): ... pass ... >>> MyClass.x <function __main__.x> >>> MyClass.x is MyClass.x True
The unrelated instance methods are bare functions in Python 3, and each search gives the same object.
source share