Using Super Without Inheritance Class In Python3
Solution 1:
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
)
>>> classABC: 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
.
>>> classABC(str): pass
...
>>> ABC.__mro__
(<class'__main__.ABC'>, <class'str'>, <class'object'>)
Regarding your question "why super
?", consider this standard example:
classA:
deffoo(self):
print("A")
classB(A):
deffoo(self):
super().foo()
print("B")
classC(A):
deffoo(self):
super().foo()
print("C")
classD(B, C):
deffoo(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 (sansobject
; A
doesn't use super
because A
"introduced" foo
into the hierarchy) in reverse order, from least to most specific.
Solution 2:
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.
>>>classIntermediate:...def__init__(self):...print(f'Intermediate init of {self.__class__.__name__}')...super().__init__()...>>>classAlphabet(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.
Solution 3:
All classes implicitly inherit from object
, just like in Java, unless they explicitly inherit from something else (which itself has to either implicitly inherit from object
or from something else, and so on...).
A byproduct of this is that you can invoke any of object
's methods on your object, ignoring your object's implementation of those methods, by doing what you've done:
>>> dir(object)
['__class__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__',
'__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__',
'__lt__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__',
'__sizeof__', '__str__', '__subclasshook__']
Post a Comment for "Using Super Without Inheritance Class In Python3"