As the docs say, functions defined in the class body are bound to class instance on demand (that is, when they're called by that instance); function object is a non-data descriptor.
This is indeed the case:
>>> class X:
... def foo(self): 1
...
>>> x = X()
>>> print(hex(id(x.foo))) # 0x7fe59020fa40
... after several seconds ...
>>> print(hex(id(x.foo))) # 0x7fe59020fbc0 <- different!
>>> print(x.foo is x.foo) # False
Pure Python equivalent of function's __get__ is:
def __get__(self, instance, owner=None):
"Simulate func_descr_get() in Objects/funcobject.c"
if instance is None:
return self
return MethodType(self, instance)
Wouldn't it be more efficient not to create an instance of MethodType, but instead just return a small wrapper? In pure Python:
def __get__(self, instance, owner=None):
"Simulate func_descr_get() in Objects/funcobject.c"
def new_func(*args, **kwargs):
return self(instance, *args, **kwargs)
return new_func if instance is not None else self
Naturally, all of this isn't written in pure Python but instead, in CPython case, it's written in C; there are probably various shortcuts on the way. But surely in C (for CPython) defining a small wrapper function is faster than instantiating a MethodType? Or not?
I'm curious why wasn't this way chosen... What drawbacks does it have, compared to instantiating MethodType on each call?