1

As I mentioned in the title I wonder why some __init__ methods are not called. Here is my example:

class Type(type):
    def __repr__(cls):
        return cls.__name__

class A(object, metaclass=Type):
    def __init__(self):
        print("A")

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

class D(object, metaclass=Type):
    def __init__(self):
        print("D")

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

class F(D, E):
    def __init__(self):
        print("F1")
        super().__init__()
        print("F2")

print(F.mro())
F()

which returns the order in which methods should be inherited (mro()) and actual results:

[F, D, E, B, A, <class 'object'>]
F1
D
F2

Why the actual results are different from:

F1
D1
E1
B1
A
B2
E2
D2
F2

as the MRO would suggest?

I know the answer half way, that is, the lack of __init__ in A's class definition breaks this chain, but why?

lunesco
  • 126
  • 3
  • 9
  • Because `D` doesn't call super, how else would the rest of the chain happen? – juanpa.arrivillaga Apr 08 '20 at 18:22
  • Yes, but `D` does not have super class. I thought it automagically calls `E`'s `__init__` after it comes out of `D`. – lunesco Apr 08 '20 at 20:22
  • No. Python will never just magically call a parent-class method if you've overriden it without providing it a means to. Note, super isn't magic. Super is returns a proxy object that will delegate the call to the appropriate method in the method resolution order, the *next method in the MRO*, not the parent class of the class the current method is defined it. In that respect, `super` isn't the best name for it. But "next_in_mro` is a mouthful. This depends on the type and instance you pass in. But it has to be used to work! – juanpa.arrivillaga Apr 08 '20 at 20:32

0 Answers0