Подтвердить что ты не робот

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

Кажется, меня бредют. Что я делаю неправильно?

4b9b3361

Ответ 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)