Ответ 1
Рассмотрим следующую ситуацию:
class A(object):
def __init__(self):
print('Running A.__init__')
super(A,self).__init__()
class B(A):
def __init__(self):
print('Running B.__init__')
# super(B,self).__init__()
A.__init__(self)
class C(A):
def __init__(self):
print('Running C.__init__')
super(C,self).__init__()
class D(B,C):
def __init__(self):
print('Running D.__init__')
super(D,self).__init__()
foo=D()
Итак, классы образуют так называемый алмаз наследования:
A
/ \
B C
\ /
D
Запуск кода дает
Running D.__init__
Running B.__init__
Running A.__init__
Это плохо, потому что C
__init__
пропущен. Причина этого в том, что B
__init__
вызывает A
__init__
напрямую.
Цель super
- разрешить алмазы наследования. Если вы не комментируете
# super(B,self).__init__()
и комментарий
A.__init__(self)
код дает более желательный результат:
Running D.__init__
Running B.__init__
Running C.__init__
Running A.__init__
Теперь все методы __init__
вызываются. Обратите внимание, что в то время, когда вы определяете B.__init__
, вы можете подумать, что super(B,self).__init__()
совпадает с вызовом A.__init__(self)
, но вы ошибаетесь. В приведенной выше ситуации super(B,self).__init__()
на самом деле вызывает C.__init__(self)
.
Святые курит, B
ничего не знает о C
, и тем не менее super(B,self)
знает, чтобы позвонить C
__init__
? Причина в том, что self.__class__.mro()
содержит C
. Другими словами, self
(или выше, foo
) знает о C
.
Поэтому будьте осторожны - они не являются взаимозаменяемыми. Они могут дать совершенно разные результаты.
Использование super
имеет подводные камни. Он требует значительного уровня координации между всеми классами диаграммы наследования. (Они должны, например, иметь одну и ту же сигнатуру вызова для __init__
, так как любой конкретный __init__
не знал, какой другой __init__
super
может вызвать следующий, или
else использовать **kwargs
.) Кроме того, вы должны быть совместимы с использованием super
везде. Пропустите его один раз (как в приведенном выше примере), и вы победите цель цели super
.
См. Ссылку для других подводных камней.
Если у вас есть полный контроль над иерархией классов или вы избегаете алмазов наследования, тогда нет необходимости в super
.