I know that super() and multi-inheritance have already been discussed here. But I did not find a solution, regarding my specific problem in python3. Let's assume we have:
#! /usr/bin/env python3
class A(object):
def __init__(self):
super().__init__()
def foo(self):
print("The")
class B(object):
def __init__(self):
super().__init__()
def foo(self):
print("world")
class C(B):
def __init__(self):
super().__init__()
def foo(self):
super().foo()
print("is")
class D(A,C):
def __init__(self):
super().__init__()
def foo(self):
super().foo()
print("nice")
d = D()
d.foo()
This will get me:
The
nice
On the other hand, if I change the order of inheritance in D() to:
class D(C,A):
def __init__(self):
super().__init__()
def foo(self):
super().foo()
print("nice")
It gives me
world
is
nice
I, however, only get the desired output:
The
world
is
nice
using:
class D(C,A):
def __init__(self):
super().__init__()
def foo(self):
A.foo(self)
C.foo(self)
print("nice")
Which I find quite unelegant.
So my question is: Is it possible to use super() in python3 invoking the super method of both super classes instead of just the first?
Unfortunately, without a knowledge of the method resolution order (MRO) of D
, there is no way to call super()
in D
to get at both base classes.
But the MRO is powerful concept. In the second case,
class D(C,A):
...
the (MRO) is
>>> D.mro()
[<class '__main__.D'>, <class '__main__.C'>, <class '__main__.B'>, <class '__main__.A'>, <class 'object'>]
Inasmuch as calling super()
takes you to the next class in the MRO, as Mr. Pieters stated, and you want the print statements coming in the order of A
, B
, C
, then D
, simply put super().foo()
first and print(...)
second in each definition of foo()
. The only exception is do not put super().foo()
in class A
because foo()
is not defined in object
.
#! /usr/bin/env python3
class A(object):
def __init__(self):
super().__init__()
def foo(self):
print("The")
class B(object):
def __init__(self):
super().__init__()
def foo(self):
super().foo() # Inserted
print("world")
class C(B):
def __init__(self):
super().__init__()
def foo(self):
super().foo()
print("is")
class D(C,A): # Correct ordering
def __init__(self):
super().__init__()
def foo(self):
super().foo()
print("nice")
d = D()
d.foo()
The MRO of D(A,C)
in the first case includes all classes as well, so with correct ordering of super()
and print(...)
statements, one can make it work:
class A(object):
def foo(self):
print("The")
super().foo()
class B(object):
def foo(self):
print("world")
class C(B):
def foo(self):
super().foo()
print("is")
class D(A,C):
def foo(self):
super().foo()
print("nice")
D().foo()
To understand inheritance order (e.g. class D(C,A)
or class D(A,C)
) and MRO, see https://www.python.org/download/releases/2.3/mro/. The C3 method resolution order is described in detail and there are nicely drawn ASCII class hierarchies with the MRO labeled.
Maybe this will help
class A(object):
def __init__(self):
super().__init__()
def foo(self):
print("The")
if hasattr(super(), 'foo'):
super().foo()
class B(object):
def __init__(self):
super().__init__()
def foo(self):
print("world")
class C(B):
def __init__(self):
super().__init__()
def foo(self):
super().foo()
print("is")
class D(A,C):
def __init__(self):
super().__init__()
def foo(self):
super().foo()
print("nice")
d = D()
d.foo()
output:
The
world
is
nice
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With