Ответ 1
Используйте не super(baseclass, ...)
, если не знаете, что делаете. Первый аргумент super()
сообщает ему, что класс пропустить при поиске следующего метода. Например. super(A, ...)
будет смотреть MRO, найти A
, а затем начать поиск __init__
в базовом классе next, не A
. Для C
MRO имеет значение (C, A, B, object)
, поэтому super(A, self).__init__
найдет B.__init__
.
В этих случаях вы не хотите использовать совместное наследование, но вместо этого ссылаетесь непосредственно на A.__init__
и B.__init__
. super()
следует использовать только в том случае, если методы, которые вы вызываете, имеют одну и ту же подпись или будут проглатывать неподдерживаемые аргументы с помощью *args
и **vargs
. В этом случае потребуется только один вызов super(C, self).__init__()
, а следующий класс в заказе MRO позаботится о цепочке вызова.
Поменяв это иначе: когда вы используете super()
, вы не можете знать, какой класс будет следующим в MRO, чтобы класс лучше поддерживал аргументы, которые вы передаете ему. Если это не так, не используйте super()
.
Вызов методов базы __init__
напрямую:
class A(object):
def __init__(self, a, b):
print('Init {} with arguments {}'.format(self.__class__.__name__, (a, b)))
class B(object):
def __init__(self, q):
print('Init {} with arguments {}'.format(self.__class__.__name__, (q)))
class C(A, B):
def __init__(self):
# Unbound functions, so pass in self explicitly
A.__init__(self, 1, 2)
B.__init__(self, 3)
Используя кооператив super()
:
class A(object):
def __init__(self, a=None, b=None, *args, **kwargs):
super().__init__(*args, **kwargs)
print('Init {} with arguments {}'.format(self.__class__.__name__, (a, b)))
class B(object):
def __init__(self, q=None, *args, **kwargs):
super().__init__(*args, **kwargs)
print('Init {} with arguments {}'.format(self.__class__.__name__, (q)))
class C(A, B):
def __init__(self):
super().__init__(a=1, b=2, q=3)