I was playing with classes to see how mro
works in python3. I got the main idea: methods are resolved left to right, depth first and if there is a common parent, it's at the end.
Here is something apparently quite simple that does not behave like I expect:
class A(object):
def f(self):
print("calling A")
print("A")
class B(A):
def f(self):
print("calling B")
super(B, self).f()
print("B")
class C(A):
def f(self):
print("calling C")
super(C, self).f()
print("C")
class D(B,C):
def f(self):
print("calling D")
super(D, self).f()
print("D")
d=D()
d.f()
Now, since the mro is D -> B -> C -> A
I expect super
to call B.f
so that it prints:
calling D
calling B
calling A
A
B
D
But it actually call C.f
too:
calling D
calling B
calling C
calling A
A
C
B
D
Why is that?
The reason I expect C.f
not to be called is that since B
as method f
, the resolution should stop. This is the case if C
does not inherit from A
:
class A(object):
def f(self):
print("calling A")
print("A")
class B(A):
def f(self):
print("calling B")
super(B, self).f()
print("B")
class C():
def f(self):
print("calling C")
super(C, self).f()
print("C")
class D(B,C):
def f(self):
print("calling D")
super(D, self).f()
print("D")
d=D()
d.f()
# prints:
# calling D
# calling B
# calling A
# A
# B
# D