Python Multiple Inheritance: выбор, который super() для вызова
В Python, как мне выбрать, какой метод Parent вызывать? Скажем, я хочу вызвать родительский метод ASDF2 __init__
. Похоже, я должен указать ASDF1 в super()..? И если я хочу вызвать ASDF3 __init__
, тогда я должен указать ASDF2?!
>>> class ASDF(ASDF1, ASDF2, ASDF3):
def __init__(self):
super(ASDF1, self).__init__()
>>> ASDF()
ASDF2 __init__ happened
>>> class ASDF(ASDF1, ASDF2, ASDF3):
def __init__(self):
super(ASDF2, self).__init__()
>>> ASDF()
ASDF3 __init__ happened
Кажется, меня бредют. Что я делаю неправильно?
Ответы
Ответ 1
Это не то, что super()
. Супер в основном выбирает одного (или всех) своих родителей в определенном порядке. Если вы хотите только вызвать один родительский метод, сделайте это
class ASDF(ASDF1, ASDF2, ASDF3):
def __init__(self):
ASDF2.__init__(self)
Ответ 2
super
вызывает следующий метод в порядке разрешения метода. В дереве линейного наследования это будет метод из сразу родительского класса.
Здесь у вас есть три родителя, а следующий __init__
метод из ASDF1
- это ASDF2
. В общем, безопасная вещь - передать первый класс в списке наследования до super
, если вы не знаете, почему вы хотите сделать что-то еще.
Цель всего этого - освободить вас от необходимости явно выбирать, какие методы __init__
вызывать. Здесь возникает вопрос, почему вы не хотите вызывать все методы суперкласса __init__
.
В python существует довольно значительная литература об использовании super
, и я рекомендую вам google тему и прочитайте, какие результаты.
Ответ 3
Вы передаете ASDF1 (один из ваших родительских классов) в качестве первого аргумента super(). Не делай этого. Вместо этого вы должны передать ASDF в качестве первого аргумента super().
Документация для Python 2.7 для супер()
Чтобы процитировать документы Python 2.7, типичный вызов суперкласса выглядит следующим образом:
class C(B):
def method(self, arg):
super(C, self).method(arg)
Обратите внимание, что первым аргументом super здесь является C, который является текущим классом. Не передавайте B (родительский класс) в super().
При определении порядка разрешения метода (MRO) супер пропускает класс, который передается в качестве первого аргумента, и начинает смотреть на родителей и братьев и сестер этого класса. Итак, когда вы передали ASDF1 в качестве первого аргумента super(), он пропустил ASDF1 и начал поиск с ASDF2. Вот почему был вызван ASDF2 __init__
.
В Python 3 вам больше не нужно передавать текущий класс.
class C(B):
def method(self, arg):
super().method(arg) # This does the same thing as:
# super(C, self).method(arg)
# (Python 3 only)