python diamond inheritance and the use of super() in the parents of the derived class
multiple-inheritance, python, python-2.7
Solution
When you call `myview2.check()`, it traverses siblings then calls the base class. Whenever one of those traversals hits `AMixin1`, `BMixin1`, or `CMixin1`, it stops, because those 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 has to work this way. Subclasses are going to assume the base class method isn't called before the subclass calls `super()`. If it is (or, worse, if it depends on the order its siblings are listed), it makes things very difficult to deal with.
Problem
First of all, I have to apologize for not having a better title. Feel free to change it if you find a more appropriate one. Basically, I have been bugged by the behaviour of Python's multiple inheritance. In my previous SO question, I got directed to read Python's C3 MRO. That really helps me to have a better understanding of multiple inheritance in Python. Just when I thought I got the grasp of it, I bumped into the following scenario, which I can't seem to make sense of. ``` 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 out a pattern based on observing the outputs, but it bugs me not understanding the rationale behind this result. I have questions like, for example, why does `myview2.check()` return ``` check A check B check C base check ``` not ``` check A base check ``` It seems to me that I am missing a key piece about multiple inheritance. Please fill in the gap for me.