Скажем, у меня есть сценарий множественного наследования:
class A(object):
# code for A here
class B(object):
# code for B here
class C(A, B):
def __init__(self):
# What the right code to write here to ensure
# A.__init__ and B.__init__ get called?
Существует два типичных подхода к написанию C
__init__
:
- (в старом стиле)
ParentClass.__init__(self)
- (в более новом стиле)
super(DerivedClass, self).__init__()
Однако в любом случае, если родительские классы (A
и B
) не следуют одному и тому же соглашению, код не будет работать правильно (некоторые могут быть пропущены или вызваны несколько раз).
Так что опять правильно? Легко сказать "просто будь последовательным, следуй тому или другому", но если A
или B
из сторонней библиотеки, что тогда? Есть ли подход, который может обеспечить вызов всех конструкторов родительских классов (и в правильном порядке, и только один раз)?
Изменение: чтобы увидеть, что я имею в виду, если я делаю:
class A(object):
def __init__(self):
print("Entering A")
super(A, self).__init__()
print("Leaving A")
class B(object):
def __init__(self):
print("Entering B")
super(B, self).__init__()
print("Leaving B")
class C(A, B):
def __init__(self):
print("Entering C")
A.__init__(self)
B.__init__(self)
print("Leaving C")
Тогда я получаю:
Entering C
Entering A
Entering B
Leaving B
Leaving A
Entering B
Leaving B
Leaving C
Обратите внимание, что B
init вызывается дважды. Если я сделаю:
class A(object):
def __init__(self):
print("Entering A")
print("Leaving A")
class B(object):
def __init__(self):
print("Entering B")
super(B, self).__init__()
print("Leaving B")
class C(A, B):
def __init__(self):
print("Entering C")
super(C, self).__init__()
print("Leaving C")
Тогда я получаю:
Entering C
Entering A
Leaving A
Leaving C
Обратите внимание, что B
init никогда не вызывается. Таким образом, кажется, что если я не знаю/не контролирую инициацию классов, которые я наследую от (A
и B
), я не могу сделать безопасный выбор для класса, который я пишу (C
).