The way this works in Python is that once you instantiate a class Foo
with a method bar(self)
, the function used to create the method is wrapped in an object of type instancemethod
which "binds" it to the instance, so that calling foo_inst.bar()
actually calls Foo.bar(foo_inst)
.
class Foo(object):
def bar(self):
print "called bar on %s" % self
foo_inst = Foo()
# these 2 calls are equivalent
foo_inst.bar()
Foo.bar(foo_inst)
or, interactively:
>>> Foo.bar
<unbound method Foo.bar>
>>> Foo().bar
<bound method Foo.bar of <__main__.Foo object at 0x10675ecd0>>
so as you can see, while still attached directly to the class, bar
is an unbound method and still has the self
argument, however, when retrieving the method object from a Foo
instance, it has become a bound method whose self
parameter is already pre-set to the instance you retrieved the method object from.
This is also the reason why self
can really be called anything you want such as arg0
or this
or me
or putin
etc.
In fact, it becomes even more visible that methods are actually functions under the hood in this example:
class Foo(object):
pass
def bar(arg0):
print "called bar with %s" % arg0
Foo.bar = bar
Foo().bar() # prints: called bar with <Foo object at 0x10675b2d0>
See also Python Descriptors @ https://docs.python.org/2/howto/descriptor.html for how this is implemented and how you can implement similar schemes yourself.