Multiple Inheritance - why does output is not as per MRO

71 Views Asked by At
class A():
    def __init__(self):
      super().__init__()
      print("A")

class B():
    def __init__(self):
      super().__init__()
      print("B")

class C(B,A):
    def __init__(self):
      super().__init__()
      print("C")

c=C()
print(C.mro())

The output of print mro is Class C, Class B, Class A and Class Object. As per that it should come something as C,B,A. But the actual output coming as C,A,B. Why is that? Is it because of super?

1

There are 1 best solutions below

3
On

What is class C's MRO?

The Method Resolution Order of a class can be found by getting its __mro__ attribute. Here is what C's MRO is:

C.__mro__
(<class '__main__.C'>, <class '__main__.B'>, <class '__main__.A'>, <class 'object'>)

However, when creating an instance of class C, this is what happens:

c = C()
A
B
C

The actual output, as seen above, is A, B, C, not C, A, B. But this is still not what was expected, and it is different to the MRO.

What is going wrong?

In each class, super().__init__() is called before print("...") is. Therefore, the order that the letters are printed out in effectively gets reversed.

Here is a diagram to explain what is happening:

__main__      C.__init__()      B.__init__()      A.__init__()      object.__init__()

  START
 c = C()    ->    START
           super().__init__()  ->   START
                             super().__init__()  ->   START
                                               super().__init__()   ->   START
                                                    print("A")     <-     END
                                  print("B")     <-    END
                print("C")     <-    END
   END      <-     END

Because the print() calls happen after the super().__init__() calls, the letters are printed in reverse order.

How to produce the correct result

In order to get the correct the result, the order of the lines within each __init__() method must be reversed so that the letter is printed out before the next class' __init__() is called.

The following code would produce the expected output:

class A():
    def __init__(self):
      print("A")  # The print() line comes first
      super().__init__()  # The super().__init__() line comes second

class B():
    def __init__(self):
      print("B")
      super().__init__()

class C(B,A):
    def __init__(self):
      print("C")
      super().__init__()

c = C()