Reputation: 33
Consider the following class:
class Foo(object):
def bar(self):
print(self)
In Python 2 (2.7.13), calling bar()
as a class method raises an exception:
>>> Foo.bar('hello')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unbound method bar() must be called with Foo instance as first argument (got str instance instead)
>>> Foo.bar()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unbound method bar() must be called with Foo instance as first argument (got nothing instead)
When bar()
is called as an instance method it recognizes self
as the instance when called without arguments
>>> Foo().bar('hello')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: bar() takes exactly 1 argument (2 given)
>>> Foo().bar()
<__main__.Foo object at 0x10a8e1a10>
In Python 3 (3.6.0), when calling bar()
as a class method, the first argument is accepted as self
:
>>> Foo.bar('hello')
hello
>>> Foo.bar()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: bar() missing 1 required positional argument: 'self'
Calling bar()
as an instance method works as in Python 2
>>> Foo().bar('hello')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: bar() takes 1 positional argument but 2 were given
>>> Foo().bar()
<__main__.Foo object at 0x104ab34a8>
Upvotes: 3
Views: 193
Reputation: 281843
On Python 3, Foo.bar
is just that bar
function you wrote. It takes one parameter, which happens to be named self
, and prints it. You can call that function on anything, and it will print whatever argument you pass it.
On Python 2, Foo.bar
isn't quite the bar
function you wrote. When you access Foo.bar
, Python generates an unbound method object wrapping the bar
function. The unbound method object works mostly like the bar
function, with the main difference of validating that its first argument is an instance of Foo
. You could do
Foo.bar(some_foo_instance)
which would work like some_foo_instance.bar()
, but calling Foo
's implementation, bypassing any overrides in subclasses. You couldn't do Foo.bar('hello')
, though.
Python 3 removed unbound method objects. They don't exist any more. That makes the language a bit simpler, but it removes the validation unbound method objects used to perform.
Upvotes: 9