¿Por qué el id () de un método no vinculado en Python 2 cambia para cada acceso?

Python 2.6.5 (r265: 79063, 1 de octubre de 2012, 22:07:21) [GCC 4.4.3]

>>> class myclass: ... def func(self): ... pass >>> dd = myclass.func >>> ee = myclass.func >>> cc = myclass.func >>> ff = myclass.func >>> ss = myclass.func >>> uu = myclass.func >>> pp = myclass.func >>> >>> >>> id(dd) ; id(cc) ; id(ee) ; id(ff) ; id(ss) ; id(uu) ; id(pp) 3074535252L 3074534772L 3074522444L 3074531732L 3074497588L 3073003604L 3073003724L 

¿Por qué la ID del método no vinculado es diferente cada vez?

¿No debería ser lo mismo?

Esto se debe a que los métodos en una clase (antiguos o nuevos) realmente funcionan como atributos con el método descriptor __get__ ; En Python 2 el código.

 foo = FooClass.bar_method 

es análogo a

 import types foo = types.MethodType(FooClass.__dict__['bar_method'], None, FooClass) 

instancemethod(bar_method, None, FooClass) una nueva instancia de instancemethod(bar_method, None, FooClass) en cada acceso. La función original está disponible como FooClass.bar_method.im_func y la instancia de clase en foo.im_class . El tipo para los métodos enlazados y no enlazados es el mismo método de instancemethod ; si el miembro im_self es None , la instancemethod instancemethod tiene la repr ilimitado , mientras que si el miembro im_self no es Ninguno, la repr es

Python 3 es diferente. Los métodos no tienen una repr y el id es siempre el mismo, es decir, son solo funciones generales. En Python 3, puede pasar cualquier cosa por self de un método sin decorar sin unir, incluso None , es solo una función con un punto en su nombre.