I'm trying to learn the super() function in Python.
I thought I had a grasp of it until I came over this example (2.6) and found myself stuck.
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "test.py", line 9, in do_something
do_something = classmethod(do_something)
TypeError: unbound method do_something() must be called with B instance as first argument (got nothing instead)
>>>
It wasn't what I expected when I read this line right before the example:
If we're using a class method, we don't have an instance to call super with. Fortunately for us, super works even with a type as the second argument. --- The type can be passed directly to super as shown below.
Which is exactly what Python tells me is not possible by saying that do_something() should be called with an instance of B.
The example from the web page seems to work as published. Did you create a
do_something
method for the superclass as well but not make it into a classmethod? Something like this will give you that error:I think I've understood the point now thanks to this beatiful site and lovely community.
If you don't mind please correct me if I'm wrong on classmethods (which I am now trying to understand fully):
I hope this illustration shows ..
Sometimes texts have to be read more for the flavor of the idea rather than for the details. This is one of those cases.
In the linked page, Examples 2.5, 2.6 and 2.7 should all use one method,
do_your_stuff
. (That is,do_something
should be changed todo_your_stuff
.)In addition, as Ned Deily pointed out,
A.do_your_stuff
has to be a class method.super(B, cls).do_your_stuff
returns a bound method (see footnote 2). Sincecls
was passed as the second argument tosuper()
, it iscls
that gets bound to the returned method. In other words,cls
gets passed as the first argument to the methoddo_you_stuff()
.So
super(B, cls).do_your_stuff()
causesA
'sdo_your_stuff
method to be called withcls
passed as the first argument. In order for that to work,A
'sdo_your_stuff
has to be a class method. The linked page doesn't mention that, but it's true.PS.
do_something = classmethod(do_something)
is the old way of making a classmethod. The new(er) way is to use the @classmethod decorator.Note that
super(B, cls)
can not be replaced bysuper(cls, cls)
. Doing so could lead to infinite loops. For example,will raise
RuntimeError: maximum recursion depth exceeded while calling a Python object
.If
cls
isC
, thensuper(cls, cls)
searchesC.mro()
for the class that comes afterC
.Since that class is
B
, whencls
isC
,super(cls, cls).do_your_stuff()
always callsB.do_your_stuff
. Sincesuper(cls, cls).do_your_stuff()
is called insideB.do_your_stuff
, you end up callingB.do_your_stuff
in an infinite loop.In Python3, the 0-argument form of
super
was added sosuper(B, cls)
could be replaced bysuper()
, and Python3 will figure out from context thatsuper()
in the definition ofclass B
should be equivalent tosuper(B, cls)
.But in no circumstance is
super(cls, cls)
(or for similar reasons,super(type(self), self)
) ever correct.I've updated the article to make it a bit clearer: Python Attributes and Methods # Super
Your example using classmethod above shows what a class method is - it passes the class itself instead of the instance as the first parameter. But you don't even need an instance to call the method, for e.g.:
In Python 3, you can skip specifying arguments for
super
,