1
class base:
    def __init__(self):
        print('base')


class F0(base):
    def __init__(self):
        super().__init__()
        print("F0")


class F1(F0):
    def __init__(self):
        super().__init__()
        print("F1")


class F2(F0):
    def __init__(self):
        super().__init__()
        print("F2")


class F3(F1, F2):
    def __init__(self):
        super().__init__()
        print("F3")

# -------------------------------------
class Base_1():
    def __init__(self):
        print('base_1')

class Base_2():
    def __init__(self):
        print('base_2')
        
class Base_3(Base_1, Base_2):
    def __init__(self):
        super().__init__()
        print("base_3")


if __name__ == '__main__':
    f3 = F3()
    print(F3.mro())

    base_3 = Base_3()
    print(Base_3.mro())

Output:

base
F0
F2
F1
F3
[<class '__main__.F3'>, <class '__main__.F1'>, <class '__main__.F2'>, <class '__main__.F0'>, <class '__main__.base'>, <class 'object'>]
base_1
base_3
[<class '__main__.Base_3'>, <class '__main__.Base_1'>, <class '__main__.Base_2'>, <class 'object'>]

Point I understand:

For Base_3 class, it inherits Base_1 and Base_2. In Base_3's init function, if I call super().__init__() it only executes Base_1's init function.

Point I don't understand:

2 classes (F1, F2) have a same father class (F0) who inherits from another class (base). Then if I call super().__init__() in F3 (which inherits F1 and F2), it will execute both F1 and F2's init function.

2 Answers 2

1

in case of base_3 there is no MRO rules applied because base_1 and base_2 are not linked to each other by inheritance
so it means that simple inheritance tree search rules are applied in case of base_3 => when you call super in base_3 that super finds first __init__ in base_1 (cuz of base_1 is lefter - Base_3(Base_1, Base_2)) and then nothing happens, super is worked
but in case of F3 its parents F1 and F2 has the same parent F0 so it mean that F0 is inherited by F3 twice == diamond problem occures(!), and this diamond problem will be solved by MRO3 but not with simple inheritance like in case of base_3

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

4 Comments

Thans for your reply! So applying "MRO" means that the program will execute the fathers' functions in the reversed order printed by .mro() ?
MRO (method resolution order) is the order in what classes inherit each other. It's easy if there are just 3 classes but when there are huge amount of classes and all them are intertwined with inheritance in a way that only devil can understand it then MRO is created by special rules. in case of python.3X this rules are called C3 linarization algorithm.
when by calling __init__ functions it 'jumps up' to grandparent base it starts to 'go down' and then execution of base's __init__ is actually the execution of super().__init__() line from F0 and execution F0's __init__ is actually execution of super().__init__() line from either F1 or F2. The fact that 'F2' is printed higher points that F2's __init__ is executed before F1's one.
And in this moment it should just 'go down' further to F0 without touching F1 but some magic happens and it does touch F1 and it's interesting why F1 and F2 here is swapped places. I guess that the essence of that 'magic' lies somewhere in C3 linarizaion. I myself have no answer for this question and I'm curious as well as you.
0

Then if I call super().init() in F3 (which inherits F1 and F2), it will execute both F1 and F2's init function.

But that is the expected case right, since:

class F3(F1, F2):
    ...

Base_3 inherits from both classes.

6 Comments

That is not my expected case (though it is wrong), since refer to the 7-th and 8-th lines of the outputl, though Base_3 inherits from Base_1 and Base_2, it only executes Base_1's init function.
Is this answer confusing F3 with Base3?
I did indeed, but still what is the expected behavior here?
My expected output of "f3 = F3()" will be " base F0 F1 " (in which there is no F2 printed)
F3 and Base3 inherit from F1,F2 and Base1, Base2, respectively. But F3.__init__'s super calls both F1 and F2, while base_3.__init__'s super only calls base_1.__init__(). The difference is that the F* hierarchy is a diamond -- both inherit from F0 and base -- whereas the base* hierarchy just terminates at base_1 and base_2.
|

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.