5
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?

8
  • 2
    Check grandchild.__mro__. Commented Nov 8, 2020 at 16:10
  • @HenryTjhia I have printed the MRO for this here: ideone.com/dhbhvT What I dont understand is, how and why is the code jumping from line 16 to line 24. Commented Nov 8, 2020 at 16:16
  • The result should be self-explainatory. Basically super routing through that tuple result. Commented Nov 8, 2020 at 16:19
  • 1
    @HenryTjhia On line 17, when super().form1() is called, it calls child2.form1() because in the MRO hierarchy, child2 is the parent (super() in child1 will return child2) of child1. Is this correct? Commented Nov 8, 2020 at 16:28
  • Why would child2 become parent of child1? Both child1 and child2 are parent of grandchild, which in turn have parent as their superclass. parent itself has implied object as their ancestor. You are calling method through instance of grandchild as consequence should follow grandchild mro pattern. Commented Nov 8, 2020 at 16:39

1 Answer 1

4

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__ of object-or-type is D -> B -> C -> A -> object and the value of type is B, then super() searches C -> 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.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.