following the tutorial on https://docs.python.org/3/tutorial/classes.html (see below) to understand the matter deeper I would have expected, that
class Foo:
def bar(self, spam='spam'):
i = 3**33
x = Foo()
meth = x.bar
func = Foo.bar
%timeit x.bar('spam') # 1
%timeit meth('spam') # 2
%timeit func(x, 'spam') # 3
should be in the order slow to fast. But it's not, the call to meth() takes 100ns, the call to func 110ns (#1 is slower as expected).
from the explanation below I would have thought, that in #2 the method f has to be unpacked into the function and the class instance, then the argument list prepended with the instance, and the function called. Why is it not slower then #3 where you have only the plain function call.
What is wrong?
If you still don’t understand how methods work, a look at the implementation can perhaps clarify matters. When a non-data attribute of an instance is referenced, the instance’s class is searched. If the name denotes a valid class attribute that is a function object, a method object is created by packing (pointers to) the instance object and the function object just found together in an abstract object: this is the method object. When the method object is called with an argument list, a new argument list is constructed from the instance object and the argument list, and the function object is called with this new argument list.
%timeitchooses this on its own (it did 1e7 loops and showed the best of 3 runs), but anyway, yes, this was reproducible, doesn't seem to be a caching issuemethdoesn't do that.