Reputation: 1795
class parent:
def __init__(self):
self.a=2
self.b=4
def form1(self):
print("calling parent from1")
print('p',self.a+self.b)
class child1(parent):
def __init__(self):
self.a=50
self.b=4
def form1(self):
print('bye',self.a-self.b)
def callchildform1(self):
print("calling parent from child1")
super().form1()
class child2(parent):
def __init__(self):
self.a=3
self.b=4
def form1(self):
print('hi',self.a*self.b)
def callchildform1(self):
print("calling parent from child2")
super().form1()
class grandchild(child1,child2):
def __init__(self):
self.a=10
self.b=4
def callingparent(self):
super().form1()
g=grandchild()
g.callchildform1()
In the above code, when I call g.callchildform1()
, according to MRO rule, the method will be first searched in the same class, then the first parent (child1 here) and then the second parent (child2).
As expected, it calls child1.callchildform1()
and executes the first line print("calling parent from child1")
. But after this, I expected that the next line super().form1()
will be executed which will call parent.form1()
but this doesnt happen. Instead, child2.form1()
is being called. Please explain why this happens?
Upvotes: 5
Views: 1478
Reputation: 32153
The documentation has a great explanation of how super()
works:
super([type[, object-or-type]])
Return a proxy object that delegates method calls to a parent or sibling class of type. This is useful for accessing inherited methods that have been overridden in a class.
The
object-or-type
determines the method resolution order to be searched. The search starts from the class right after the type.
For example, if
__mro__
ofobject-or-type
isD -> B -> C -> A -> object
and the value of type isB
, thensuper()
searchesC -> A -> object
.
super()
is equivalent to the expression super(__class__, self)
where __class__
is an class object within whose method the super()
is called. For example, super()
within grandchild.callingparent(self)
is essentially super(grandchild, self)
. And super()
inside child1.callchildform1(self)
function is super(child1, self)
.
MRO
for grandchild
is (<grandchild>, <child1>, <child2>, <parent>, <object>)
. Therefore, according to the above excerpt from documentation, when super().form1()
is called in child1.callchildform1()
, which is equivalent to super(child1, self)
, the search for the form1
method starts from the class right after the child1
in the MRO
sequence and the first matching class with form1
method is child2
.
This occurs due to that you are using the diamond inheritance structure and the principles that underlie the MRO:
with multiple inheritance hierarchies, the construction of the linearization is more cumbersome, since it is more difficult to construct a linearization that respects local precedence ordering and monotonicity.
When designing such hierarchies, it is need to follow the approach of cooperative inheritance, an explanation can be found, in this already classic article.
Upvotes: 4