Reputation: 19803
Newbie question on super()
: In the toy example below, I was surprised that the output is C
and not A
since J
in inherits foo
from A
. Here is the code:
class A:
def foo(self):
return 'A'
class C(A):
def foo(self):
return 'C'
class J(A):
pass
class E(J, C):
def f(self):
return super().foo()
def foo(self):
return 'E'
print(E().f())
J
inherits foo
from A
; the MRO of E is:
(<class '__main__.E'>, <class '__main__.J'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>)
so how come 'A' isn't the return value? ie evaluation proceeds to C
Upvotes: 0
Views: 39
Reputation: 22314
The class super
does not just recover the superclass. It instantiate an object which recovers methods in the context of a given method resolution order. This answer features a reimplementation of super
in Python to help you understand how it resolves a method inheritance.
So, as you can see, the method resolution order of your class is (E, J, C, A, object)
. Since it comes up first, then E
inherits foo
from C
and not A
.
Now the question you are probably asking is...
C
comes before A
?The C3 linearization algorithm which builds the mro has the property that if some class X
inherits from Y
, then it will come prior to Y
in the mro.
As you can see, this is respected in your example. The class C
inherits from A
and thus has to come first.
The following example demonstrates that as soon as you were to drop the A
inheritance from C
, then the result becomes the one you were mistakingly expecting.
class A:
pass
class C: # Dropped A inheritance
pass
class J(A):
pass
class E(J, C):
pass
E.__mro__ # (E, J, A, C, object)
Upvotes: 3