anyone know what it means for following code on super(xxx, self).__init__()
? what does it do? I though it should be class ABC inherits from other class but I do not see which class is inherited from.
class ABC:
def __init__(self):
super(ABC, self).__init__()
super
works with the method resolution order (MRO) of the class. The MRO always contains at least two classes: the class itself, and object
(because all classes implicitly inherit from object
)
>>> class ABC: pass
...
>>> ABC.__mro__
(<class '__main__.ABC'>, <class 'object'>)
If there are any explicitly named base classes in the class
statement, those and their base classes will appear in the MRO somewhere between the new class and object
.
>>> class ABC(str): pass
...
>>> ABC.__mro__
(<class '__main__.ABC'>, <class 'str'>, <class 'object'>)
Regarding your question "why super
?", consider this standard example:
class A:
def foo(self):
print("A")
class B(A):
def foo(self):
super().foo()
print("B")
class C(A):
def foo(self):
super().foo()
print("C")
class D(B, C):
def foo(self):
super().foo()
print("D")
The MRO for D
is (D, B, C, A)
. Notice the call super().foo
in B.foo
. Looking only at the class B
, you might assume that super().foo()
is a call to A.foo
. But when self
is an instance of D
(as is the case with D().foo()
, for example), then super
refers to C
, not A
, because C
comes immediately after B
in the MRO.
>>> D().foo()
A
C
B
D
foo
outputs the classes in the MRO (sans object
; A
doesn't use super
because A
"introduced" foo
into the hierarchy) in reverse order, from least to most specific.
Classes without explicit bases automatically inherit from object
. When called via ABC()
, the super(ABC, self).__init__()
inside ABC.__init__
executes object.__init__
. This can be seen by checking the method resolution order.
>>> ABC.__mro__
(__main__.ABC, object)
Methods that do nothing but invoke the super method are generally not needed. However, when adding functionality it is common to invoke super
even to refer to object
.
Notably, super
dispatch is not static, but can change via inheritance. Multiple inheritance can be used to inject another class between ABC
and object
in the method resolution order.
>>> class Intermediate:
... def __init__(self):
... print(f'Intermediate init of {self.__class__.__name__}')
... super().__init__()
...
>>> class Alphabet(ABC, Intermediate):
... """Compound of ABC and Intermediate"""
...
>>> Alphabet.__mro__ # Intermediate is between ABC and object...
(__main__.Alphabet, __main__.ABC, __main__.Intermediate, object)
>>> Alphabet.__init__ is ABC.__init__ # ... but __init__ is still identical!
True
>>> Alphabet() # Alphabet's ABC.__init__ delegates to Intermediate.__init__ ...
Intermediate init of Alphabet
>>> ABC() # ... but ABC's ABC.__init__ still does not.
A class such as Intermediate
is generally known as a mixin. In Python, classes intended to be used with mixins must use super
instead of directly referring to superclass methods.
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