Рассмотрим следующий пример:
class A:
def __init__(self, a, **kwargs):
print('A.__init__ called')
self.a = a
super().__init__(**kwargs)
print('A.__init__ finished')
class B:
def __init__(self, b, **kwargs):
print('B.__init__ called')
self.b = b
super().__init__(**kwargs)
print('B.__init__ finished')
class C(A, B):
def __init__(self, c, **kwargs):
print('C.__init__ called')
self.c = c
super().__init__(**kwargs)
print('C.__init__ finished')
При создании объекта C
выходные данные выглядят следующим образом:
>>> C(a=1, b=2, c=3)
C.__init__ called
A.__init__ called
B.__init__ called
B.__init__ finished
A.__init__ finished
C.__init__ finished
<__main__.C object at 0x7fd15abcab70>
Из порядка, в котором используются методы __init__
и тот факт, что они заканчиваются sh в обратном порядке, мы можем видеть, что C.__init__
вызывает A.__init__
, что вызывает B.__init__
. То есть, хотя A
не имеет явного родительского класса (поэтому его прямым родителем является object
), вызов super().__init__
в A
фактически вызывает B.__init__
.
Это потому, что B
следующий класс после A
в C
порядке разрешения метода (MRO). Класс A
должен вызывать super()
, потому что хотя его суперкласс object
, Python допускает множественное наследование, поэтому A
не может гарантировать, что это последний класс перед object
в MRO.
>>> C.__mro__
(<class '__main__.C'>, <class '__main__.A'>, <class '__main__.B'>, <class 'object'>)
См. Статью Раймона Хеттингера Python super () считается super! для более подробного объяснения MRO и "кооперативных методов множественного наследования".