Multiple inheritance and a broken super() chain
Peter Slížik
peter.slizik at gmail.com
Mon Jul 3 13:38:08 EDT 2023
Hello.
The legacy code I'm working with uses a classic diamond inheritance. Let me
call the classes *Top*, *Left*, *Right*, and *Bottom*.
This is a trivial textbook example. The classes were written in the
pre-super() era, so all of them initialized their parents and Bottom
initialized both Left and Right in this order.
The result was expected: *Top* was initialized twice:
Top.__init__() Left.__init__() Top.__init__() Right.__init__()
Bottom.__init__()
Now I replaced all parent init calls with *super()*. After this, Top was
initialized only once.
Top.__init__() Right.__init__() Left.__init__() Bottom.__init__()
But at this point, I freaked out. The code is complex and I don't have the
time to examine its inner workings. And before, everything worked correctly
even though Top was initialized twice. So I decided to break the superclass
chain and use super() only in classes inheriting from a single parent. My
intent was to keep the original behavior but use super() where possible to
make the code more readable.
class Top:
def __init__(self):
print("Top.__init__()")
class Left(Top):
def __init__(self):
super().__init__()
print("Left.__init__()")
class Right(Top):
def __init__(self):
super().__init__()
print("Right.__init__()")
class Bottom(Left, Right):
def __init__(self):
Left.__init__(self) # Here I'm calling both parents manually
Right.__init__(self)
print("Bottom.__init__()")
b = Bottom()
The result has surprised me:
Top.__init__() Right.__init__() Left.__init__() Top.__init__()
Right.__init__() Bottom.__init__()
Now, as I see it, from the super()'s point of view, there are two
inheritance chains, one starting at Left and the other at Right. But
*Right.__init__()* is called twice. What's going on here?
Thanks,
Peter
More information about the Python-list
mailing list