Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

using super without inheritance class in python3

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__()
like image 553
jacobcan118 Avatar asked Dec 31 '22 06:12

jacobcan118


2 Answers

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.

like image 79
chepner Avatar answered Jan 02 '23 20:01

chepner


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.

like image 34
MisterMiyagi Avatar answered Jan 02 '23 19:01

MisterMiyagi