Consider the following code.
class Foo:
def bar(self, x):
pass
foo1 = Foo()
foo2 = Foo()
foobar1 = foo1.bar
foobar2 = foo2.bar #What are foobar1 and foobar2?
print(foobar1 is foobar2) #prints False. Why?
On the one hand, I can see why foobar1 is not foobar2–if I call foobar1(some_arg) , the call should in general be independent of foo2 and vice versa. But don't foobar1 and foobar2 both refer to function object defined inside the class Foo?
If
method_nameis actually defined in the class object ofobject's class, then<object>.<method_name>is a "bound method" (or closure), which effectively wraps the function from the class method in order to provide<object>as theselfargument. Ifmethod_nameis actually an attribute of<object>, or if it has been marked with the@staticmethoddecorator, then<object>.<method_name>just the function itself.That's a bit of an oversimplification. There's lots more information in the Python reference manual (for example, in the "Callable objects" section of Section 3.2, The standard type hierarchy, and, iirc, in the Python tutorial. I hope this is a reasonable starting point, but for the nitty-gritty details and a full understanding of all the corner cases, you should probably read the authentic docs.
When you call
foobar1orfoobar2, you supply one argument and the function gets called with two arguments. How do you suppose that happens?More specifically, when you call
foobar1, the methodbarwill be passedfoo1as theselfargument, while when you callfoobar2, the method bar will be passedfoo2. That seems like magic, but it has a simple cause: when you extracted thebarattribute fromfoo1(foo1.bar), Python noticed that it didn't come fromfoo1itself; rather, it came from the classFoo. Since it came from the class object, Python created a new function closure on the fly in whichselfis bound tofoo1. Thus, when you later call the closure, theselfargument is filled in from the closure.You don't even need
foo2to see that. Every time you ask for thebarattribute of an instance of classFoo, you get a new closure. But that doesn't happen when you ask for thebarattribute of the class itself. In that case, the attributebaris directly available, and no closure is constructed:You can see that these are different things:
The first one is a "bound method" (where
selfhas been bound to a value), and the second one is just a garden variety function.If you try to call
Foo.bar, you'll notice that you need to supply the self argument yourself, precisely because you're calling a function and not a closure: