Inheriting python diamond and using super () in parents of a derived class

First of all, I have to apologize for not having a better title. Feel free to change it if you find a more suitable one.

Basically, I was hooked on Python's multiple inheritance behavior. In the previous question previous SO> I was asked to read the Python C3 MRO . It really helps me better understand multiple inheritance in Python. Just when I thought I understood this, I came across the following scenario, which I can not understand.

class UltimateBase(object): def check(self): print 'base check' class AMixin1(UltimateBase): def check(self): print 'check A' class BMixin1(UltimateBase): def check(self): print 'check B' class CMixin1(UltimateBase): def check(self): print 'check C' class AMixin2(UltimateBase): def check(self): print 'check A' return super(AMixin2, self).check() class BMixin2(UltimateBase): def check(self): print 'check B' return super(BMixin2, self).check() class CMixin2(UltimateBase): def check(self): print 'check C' return super(CMixin2, self).check() class MyView1(AMixin1, BMixin1, CMixin1): pass class MyView2(AMixin2, BMixin2, CMixin2): pass class MyView3(AMixin1, BMixin2, CMixin2): pass class MyView4(AMixin2, BMixin1, CMixin2): pass class MyView5(AMixin2, BMixin2, CMixin1): pass class MyView6(AMixin1, BMixin1, CMixin2): pass class MyView7(AMixin1, BMixin2, CMixin1): pass class MyView8(AMixin2, BMixin1, CMixin1): pass myview1 = MyView1() myview2 = MyView2() myview3 = MyView3() myview4 = MyView4() myview5 = MyView5() myview6 = MyView6() myview7 = MyView7() myview8 = MyView8() myview1.check() print '------------------------' myview2.check() print '------------------------' myview3.check() print '------------------------' myview4.check() print '------------------------' myview5.check() print '------------------------' myview6.check() print '------------------------' myview7.check() print '------------------------' myview8.check() print '------------------------' 

Outputs:

 check A ------------------------ check A check B check C base check ------------------------ check A ------------------------ check A check B ------------------------ check A check B check C ------------------------ check A ------------------------ check A ------------------------ check A check B ------------------------ 

I can trace the pattern based on the observation of the outputs, but this does not allow me to understand the meaning of this result.

I have questions such as, for example, why myview2.check() returns

 check A check B check C base check 

not

 check A base check 

It seems to me that I miss the keyword on multiple inheritance. Please fill in the blank for me.

+6
source share
2 answers

When you call myview2.check() , it traverses the siblings, then calls the base class. Whenever one of these AMixin1 hits AMixin1 , BMixin1 or CMixin1 , it stops because these classes do not call super(..., self).check() .

As Benn points out, this is described in the official Python documentation. And if you think about it, it pretty much should work that way. Subclasses assume that the base class method is not called before the subclass calls super() . If this (or, even worse, if it depends on how his brothers and sisters are listed), this complicates the matter.

+4
source

I tried to reflect on the same issue. I found that the following code helped simplify the problem:

(Basically, when all super were removed for a class, that class is called.)

 class A: def f(self): print("............A: the common base of B and C") class B(A): def f(self): print("........B: the left base of D") super().f() class C(A): def f(self): print("........C: the right base of D") super().f() class D(B,C): def f(self): print("....D: the top class") super().f() d = D() df() 

Conclusion:

 ....D: the top class ........B: the left base of D ........C: the right base of D ............A: the common base of B and C 

Try online

+1
source

Source: https://habr.com/ru/post/912528/


All Articles