Поведение Python __init__ с множественным наследованием [дубликат]

Наряду с принятым ответом, который правильно объяснил проблему, в понимании вашего списка, если вы используете python-2.x, используйте xrange(), который возвращает более эффективный генератор (range() в python 3 выполняет ту же работу ) _ вместо переменной throw n:

[[1]*4 for _ in xrange(3)]      # and in python3 [[1]*4 for _ in range(3)]

Кроме того, в качестве более Pythonic способа вы можете использовать itertools.repeat() для создания объекта итератора повторяющихся элементов:

>>> a=list(repeat(1,4))
[1, 1, 1, 1]
>>> a[0]=5
>>> a
[5, 1, 1, 1]

PS Используя numpy, если вы хотите создать только массив единиц или нулей, вы можете использовать np.ones и np.zeros и / или для использования других чисел np.repeat():

In [1]: import numpy as np

In [2]: 

In [2]: np.ones(4)
Out[2]: array([ 1.,  1.,  1.,  1.])

In [3]: np.ones((4, 2))
Out[3]: 
array([[ 1.,  1.],
       [ 1.,  1.],
       [ 1.,  1.],
       [ 1.,  1.]])

In [4]: np.zeros((4, 2))
Out[4]: 
array([[ 0.,  0.],
       [ 0.,  0.],
       [ 0.,  0.],
       [ 0.,  0.]])

In [5]: np.repeat([7], 10)
Out[5]: array([7, 7, 7, 7, 7, 7, 7, 7, 7, 7])

620
задан Peter O. 29 July 2014 в 21:39
поделиться

11 ответов

Это подробно описано с достаточным количеством подробностей самим Гвидо в его сообщении в блоге Order Resolution (включая две предыдущие попытки).

В вашем примере Third() вызовет First.__init__. Python ищет каждый атрибут в родителях класса, поскольку они перечислены слева направо. В этом случае мы ищем __init__. Итак, если вы определите

class Third(First, Second):
    ...

, Python начнет с просмотра First, и, если First не имеет атрибута, тогда он будет смотреть на Second.

Эта ситуация становится более сложной, когда наследование начинает пересекать пути (например, если First унаследовано от Second). Прочтите ссылку выше для более подробной информации, но, в двух словах, Python попытается сохранить порядок, в котором каждый класс появится в списке наследования, начиная с самого дочернего класса.

Так, например, если у вас есть:

class First(object):
    def __init__(self):
        print "first"

class Second(First):
    def __init__(self):
        print "second"

class Third(First):
    def __init__(self):
        print "third"

class Fourth(Second, Third):
    def __init__(self):
        super(Fourth, self).__init__()
        print "that's it"

, MRO будет [Fourth, Second, Third, First].

. Кстати: если Python не может найти порядок согласованного метода, он вызовет исключение, вместо этого о возврате к поведению, которое может удивить пользователя.

Отредактировано, чтобы добавить пример двусмысленного MRO:

class First(object):
    def __init__(self):
        print "first"

class Second(First):
    def __init__(self):
        print "second"

class Third(First, Second):
    def __init__(self):
        print "third"

Если MF Third будет [First, Second] или [Second, First]? Нет очевидного ожидания, и Python вызовет ошибку:

TypeError: Error when calling the metaclass bases
    Cannot create a consistent method resolution order (MRO) for bases Second, First

Редактирование: я вижу, что несколько человек утверждают, что в приведенных выше примерах нет вызовов super(), поэтому позвольте мне объяснить: точка примеров чтобы показать, как строится MRO. Они не предназначены для печати «first\nsecond \ third» или что-то еще. Вы можете - и должны, конечно, поиграть с примером, добавить super() звонки, посмотреть, что произойдет, и получить более глубокое понимание модели наследования Python. Но моя цель состоит в том, чтобы держать его простым и показать, как строится MRO. И он построен, как я объяснил:

>>> Fourth.__mro__
(<class '__main__.Fourth'>,
 <class '__main__.Second'>, <class '__main__.Third'>,
 <class '__main__.First'>,
 <type 'object'>)
509
ответ дан akaihola 21 August 2018 в 01:17
поделиться
  • 1
    Это становится более интересным (и, возможно, более запутанным), когда вы начинаете называть super () в First, Second и Third [ pastebin.com/ezTyZ5Wa ]. – gatoatigrado 10 July 2012 в 01:37
  • 2
    Я думаю, что отсутствие супервызов в первых классах - действительно большая проблема с этим ответом; не обсуждая, как / почему это важное критическое понимание вопроса утеряно. – Sam Hartman 7 December 2013 в 22:14
  • 3
    Этот ответ просто ошибочен. Без вызовов super () в родителях ничего не произойдет. @ безжизненный ответ правильный. – Cerin 17 October 2015 в 01:01
  • 4
    @Cerin. Цель этого примера - показать, как сконструирована MRO. Пример НЕ предназначен для печати "first\nsecond \ third & quot; или что-то еще. И MRO действительно прав: четвертый .__ mro__ == (& lt; class ' main .Fourth' & gt ;, & lt; class ' main . Второй раз & lt ;, lt , класс ' main . Третий' & gt ;, & lt; class ' main . Первый' & gt ;, & lt; type 'object' & gt;); – rbp 17 October 2015 в 10:30
  • 5
    @gatoatigrado прав, когда говорит, что он становится более запутанным. Я следовал его логике, чтобы попытаться понять MRO и супер в глубину. Здесь я узнал. Теперь мне ясно, что в этом случае Second.super вызовет Third, хотя Third не наследуется Second. – pedrovgp 31 January 2017 в 13:26

Это касается того, как я решил выдать множественное наследование с разными переменными для инициализации и иметь несколько MixIns с тем же вызовом функции. Мне пришлось явно добавлять переменные в переданные ** kwargs и добавлять интерфейс MixIn в качестве конечной точки для супервызов.

Здесь A - расширяемый базовый класс, а B и C - MixIn классы, которые предоставляют функцию f. A и B оба ожидают параметр v в своих __init__ и C ожидает w. Функция f принимает один параметр y. Q наследуется от всех трех классов. MixInF - это интерфейс mixin для B и C.


class A(object):
    def __init__(self, v, *args, **kwargs):
        print "A:init:v[{0}]".format(v)
        kwargs['v']=v
        super(A, self).__init__(*args, **kwargs)
        self.v = v


class MixInF(object):
    def __init__(self, *args, **kwargs):
        print "IObject:init"
    def f(self, y):
        print "IObject:y[{0}]".format(y)


class B(MixInF):
    def __init__(self, v, *args, **kwargs):
        print "B:init:v[{0}]".format(v)
        kwargs['v']=v
        super(B, self).__init__(*args, **kwargs)
        self.v = v
    def f(self, y):
        print "B:f:v[{0}]:y[{1}]".format(self.v, y)
        super(B, self).f(y)


class C(MixInF):
    def __init__(self, w, *args, **kwargs):
        print "C:init:w[{0}]".format(w)
        kwargs['w']=w
        super(C, self).__init__(*args, **kwargs)
        self.w = w
    def f(self, y):
        print "C:f:w[{0}]:y[{1}]".format(self.w, y)
        super(C, self).f(y)


class Q(C,B,A):
    def __init__(self, v, w):
        super(Q, self).__init__(v=v, w=w)
    def f(self, y):
        print "Q:f:y[{0}]".format(y)
        super(Q, self).f(y)
21
ответ дан brent.payne 21 August 2018 в 01:17
поделиться
  • 1
    Я думаю, что это, возможно, отдельный вопрос и ответ, поскольку MRO является достаточно большой темой самостоятельно, не затрагивая различные аргументы между функциями с наследованием (множественное наследование - частный случай). – lifeless 1 December 2014 в 11:21
  • 2
    Теоретически, да. Практически этот сценарий возникал каждый раз, когда я сталкивался с наложением Diamond на python, поэтому я добавил его здесь. Так вот, я здесь каждый раз, когда я не могу полностью избежать наследования алмазов. Вот некоторые дополнительные ссылки для будущего меня: rhettinger.wordpress.com/2011/05/26/super-considered-super code.activestate.com/recipes/… – brent.payne 3 December 2014 в 21:40
  • 3
    Нам нужны программы с семантически значимыми именами параметров. Но в этом примере почти все параметры анонимно названы, что сделает его намного сложнее для оригинального программиста документировать код и для другого программиста читать код. – Arthur 29 November 2016 в 14:55
  • 4
    Запрос на получение репликации github с описательными именами будет оценен – brent.payne 29 November 2016 в 21:41
  • 5
    @ brent.payne Я думаю, что @Arthur означало, что весь ваш подход основан на использовании args / kwargs, а не названных параметров. – max 11 June 2017 в 23:00

Я хотел немного уточнить ответ безжизненным , потому что, когда я начал читать о том, как использовать super () в иерархии множественного наследования в Python, я не получил его немедленно.

Что вам нужно понять, так это то, что super(MyClass, self).__init__() предоставляет следующий метод next __init__ в соответствии с используемым алгоритмом упорядочивания разрешения метода (MRO) в контексте полного наследования иерархия .

Эта последняя часть имеет решающее значение для понимания. Рассмотрим снова пример:

class First(object):
  def __init__(self):
    super(First, self).__init__()
    print "first"

class Second(object):
  def __init__(self):
    super(Second, self).__init__()
    print "second"

class Third(First, Second):
  def __init__(self):
    super(Third, self).__init__()
    print "that's it"

В соответствии с этой статьей о порядке разрешения метода Гвидо ван Россума вычисляется порядок разрешения __init__ (до Python 2.3) используя «перекос по левому краю по глубине»:

Third --> First --> object --> Second --> object

После удаления всех дубликатов, кроме последнего, получаем:

Third --> First --> Second --> object

Итак, позволяет следить за тем, что происходит, когда мы создаем экземпляр класса Third, например x = Third().

  1. В соответствии с MRO __init__ третьего вызывается первым.
  2. Далее, согласно MRO, внутри метода __init__ super(Third, self).__init__() разрешается __init__ метод First, который вызывается.
  3. Внутри __init__ Первого super(First, self).__init__() вызывает __init__ из Во-вторых, потому что это то, что диктует MRO!
  4. Внутри __init__ of Second super(Second, self).__init__() вызывает __init__ объекта, что ничего не значит. После этого будет напечатан «второй».
  5. После завершения super(First, self).__init__() будет напечатан «первый».
  6. После завершения super(Third, self).__init__() будет напечатан «это все».

Это объясняет, почему создание экземпляра Third () приводит к:

>>> x = Third()
second
first
that's it

. Алгоритм MRO был улучшен с Python 2.3, чтобы хорошо работать в сложных случаях, но я думаю что использование «перемотки по глубине слева направо» + «удаление дубликатов ожидается для последнего» все еще работает в большинстве случаев (прокомментируйте, если это не так). Обязательно прочитайте сообщение в блоге Guido!

124
ответ дан Community 21 August 2018 в 01:17
поделиться
  • 1
    Я до сих пор не понимаю, почему: Inside init First super (First, self) .__ init __ () вызывает init Second, потому что это то, что диктует MRO! – user389955 20 September 2017 в 19:52
  • 2
    @ user389955 Созданный объект имеет тип Third, который имеет все методы init. Поэтому, если вы предполагаете, что MRO создает список всех функций init в определенном порядке, при каждом супервызове вы делаете один шаг вперед, пока не достигнете конца. – Sreekumar R 13 January 2018 в 19:10
  • 3
    Я думаю, что шаг 3 нуждается в дополнительном объяснении: если Third не наследовал от Second, тогда super(First, self).__init__ вызывет object.__init__ и после возвращения, «первым», будут напечатаны. Но поскольку Third наследует как First, так и Second, а не вызывает object.__init__ после First.__init__, MRO диктует, что сохраняется только окончательный вызов object.__init__, а операторы печати в First и Second не будут достигнуты до тех пор, пока object.__init__ не вернется. Поскольку Second был последним для вызова object.__init__, он возвращается внутри Second, прежде чем вернуться в First. – MountainDrew 14 February 2018 в 17:45
  • 4
    Ты прибил его, очень хорошее объяснение! Кодос! – Ghasan Al-Sakkaf 19 February 2018 в 10:45
  • 5
    Интересно, что PyCharm, похоже, знает все это (в его подсказках говорится о том, какие параметры идут с вызовами супер, а также имеет некоторое представление о ковариации входов, поэтому он распознает List[subclass] как List[superclass], если subclass является подклассом из superclass (List поступает от модуля typing PEP 483 iirc). – Reb.Cabin 9 May 2018 в 01:58

Ваш код и другие ответы являются ошибками. Они пропускают вызовы super() в первых двух классах, которые необходимы для совместной работы подкласса.

Вот фиксированная версия кода:

class First(object):
    def __init__(self):
        super(First, self).__init__()
        print("first")

class Second(object):
    def __init__(self):
        super(Second, self).__init__()
        print("second")

class Third(First, Second):
    def __init__(self):
        super(Third, self).__init__()
        print("third")

Вызов super() находит следующий метод в MRO на каждом шаге, поэтому First и Second также должны иметь его, иначе выполнение останавливается в конце Second.__init__().

Это то, что я get:

>>> Third()
second
first
third
181
ответ дан jojo 21 August 2018 в 01:17
поделиться
  • 1
    Что делать, если эти классы нуждаются в разных параметрах для инициализации? – calfzhou 8 May 2014 в 10:23
  • 2
    «совместное подклассу» – Quant Metropolis 5 September 2014 в 12:13
  • 3
    Таким образом, будут выполняться методы init базовых классов BOTH, в то время как в исходном примере вызывается только первый init , встречающийся в MRO. Я предполагаю, что это подразумевается под термином «кооперативное подклассирование», но пояснение было бы полезно («Явный лучше, чем неявный», вы знаете;)) – Quant Metropolis 5 September 2014 в 12:19
  • 4
    Да, если вы передаете разные параметры методу, вызываемому через супер, все реализации этого метода, идущие вверх по MRO к объекту (), должны иметь совместимые подписи. Это может быть достигнуто с помощью параметров ключевого слова: принимать больше параметров, чем использует метод, и игнорировать дополнительные. Обычно это считается уродливым, и для большинства случаев лучше добавлять новые методы, но init уникален как имя специального метода, но с определенными пользователем параметрами. – lifeless 1 December 2014 в 11:15
  • 5
    Дизайн наследования multiple на самом деле очень плохой в python. Базовые классы почти должны знать, кто его будет выводить, и сколько других базовых классов будет выведено производным и в каком порядке ... иначе super либо не сработает (потому что несоответствия параметров), или он не будет вызывать несколько оснований (потому что вы не пишете super в одной из базы, которая разрывает ссылку)! – Nawaz 9 November 2016 в 14:12

О комментарии @ calfzhou , вы можете использовать, как обычно, **kwargs:

Пример работы в режиме онлайн

class A(object):
  def __init__(self, a, *args, **kwargs):
    print("A", a)

class B(A):
  def __init__(self, b, *args, **kwargs):
    super(B, self).__init__(*args, **kwargs)
    print("B", b)

class A1(A):
  def __init__(self, a1, *args, **kwargs):
    super(A1, self).__init__(*args, **kwargs)
    print("A1", a1)

class B1(A1, B):
  def __init__(self, b1, *args, **kwargs):
    super(B1, self).__init__(*args, **kwargs)
    print("B1", b1)


B1(a1=6, b1=5, b="hello", a=None)

Результат:

A None
B hello
A1 6
B1 5

Вы также можете использовать их позиционно:

B1(5, 6, b="hello", a=None)

, но вы должны помнить MRO, это действительно запутанно.

Я могу быть немного раздражающим, но я заметил, что люди каждый раз забыли использовать *args и **kwargs, когда они переопределяют метод, в то время как это одно из немногих действительно полезных и разумных способов использования этих «магических переменных».

13
ответ дан Marco Sulla 21 August 2018 в 01:17
поделиться
  • 1
    Вау, это действительно уродливо. Жаль, вы не можете просто сказать, какой конкретный суперкласс вы хотите назвать. Тем не менее, это дает мне еще больший стимул использовать композицию и избегать множественного наследования, такого как чума. – Tom Busby 6 February 2017 в 16:55

Я хотел бы добавить к , что @Visionscaper говорит вверху:

Third --> First --> object --> Second --> object

В этом случае интерпретатор не отфильтровывает класс объекта, потому что его дублированный, скорее потому что второй появляется в позиции головы и не появляется в позиции хвоста в подмножестве иерархии. Хотя объект появляется только в хвостовых позициях и не считается сильной позицией в алгоритме C3 для определения приоритета.

Линеаризация (mro) класса C, L (C), является

  • Класс C
  • плюс слияние линеаризации его родителей P1, P2, .. = L (P1, P2, ...) и список его родителей P1, P2, ..

Линеаризированное слияние выполняется путем выбора общих классов, которые отображаются в виде главы списков, а не хвоста, начиная с вопросов порядка (станет ясно ниже)

линеаризация третьего может быть вычислена следующим образом:

    L(O)  := [O]  // the linearization(mro) of O(object), because O has no parents

    L(First)  :=  [First] + merge(L(O), [O])
               =  [First] + merge([O], [O])
               =  [First, O]

    // Similarly, 
    L(Second)  := [Second, O]

    L(Third)   := [Third] + merge(L(First), L(Second), [First, Second])
                = [Third] + merge([First, O], [Second, O], [First, Second])
// class First is a good candidate for the first merge step, because it only appears as the head of the first and last lists
// class O is not a good candidate for the next merge step, because it also appears in the tails of list 1 and 2, 
                = [Third, First] + merge([O], [Second, O], [Second])
// class Second is a good candidate for the second merge step, because it appears as the head of the list 2 and 3
                = [Third, First, Second] + merge([O], [O])            
                = [Third, First, Second, O]

Таким образом, для реализации super () в следующем коде:

class First(object):
  def __init__(self):
    super(First, self).__init__()
    print "first"

class Second(object):
  def __init__(self):
    super(Second, self).__init__()
    print "second"

class Third(First, Second):
  def __init__(self):
    super(Third, self).__init__()
    print "that's it"

становится очевидным, как этот метод будет разрешен

Third.__init__() ---> First.__init__() ---> Second.__init__() ---> 
Object.__init__() ---> returns ---> Second.__init__() -
prints "second" - returns ---> First.__init__() -
prints "first" - returns ---> Third.__init__() - prints "that's it"
1
ответ дан Md. Abu Nafee Ibna Zahid 21 August 2018 в 01:17
поделиться
  • 1
    «скорее, потому что второй появляется в положении головы и не появляется в положении« хвост »в подмножестве иерархии». Неясно, какова позиция головы или хвоста, а также какое подмножество иерархии или какое подмножество вы имеете в виду. – OrangeSherbet 18 July 2017 в 21:37
  • 2
    Положение хвоста относится к классам, которые выше в иерархии классов и наоборот. Объект базового класса находится в конце хвоста. Ключом к пониманию алгоритма mro является то, как «Второй» появляется как супер «Первого». Обычно мы предполагаем, что это класс «объект». Это правда, но только в перспективе класса «Первый». Однако, если смотреть с точки зрения «третьего» класса, порядок иерархии для «Первого» отличается и вычисляется, как показано выше. mro пытается создать эту перспективу (или подмножество иерархии) для всех множественных унаследованных классов – supi 22 July 2017 в 13:05

Это называется проблемой Diamond , страница имеет запись на Python, но, коротко, Python вызовет методы суперкласса слева направо.

45
ответ дан Peter Mortensen 21 August 2018 в 01:17
поделиться
  • 1
    Это не проблема алмазов. Проблема Алмаза включает в себя четыре класса, и вопрос ОФ включает только три. – Ian Goodfellow 6 August 2011 в 17:14
  • 2
    object - четвертый – GP89 26 October 2011 в 14:30
class First(object):
  def __init__(self, a):
    print "first", a
    super(First, self).__init__(20)

class Second(object):
  def __init__(self, a):
    print "second", a
    super(Second, self).__init__()

class Third(First, Second):
  def __init__(self):
    super(Third, self).__init__(10)
    print "that's it"

t = Third()

Выход -

first 10
second 20
that's it

Call to Third () определяет init, определенный в третьем. И вызов super в этой процедуре вызывает init, определенный в First. MRO = [Первый, Второй]. Теперь вызов super в init, определенный в First, продолжит поиск MRO и найдет init, определенный во втором, и любой вызов super ударит объект init по умолчанию. Надеюсь, этот пример прояснит концепцию.

Если вы не называете super от First. Цепь останавливается, и вы получите следующий результат.

first 10
that's it
4
ответ дан Seraj Ahmad 21 August 2018 в 01:17
поделиться
  • 1
    это потому, что в классе Сначала вы сначала назовите 'print', затем 'super'. – rocky qi 25 February 2016 в 03:00
  • 2
    это должно было показать призвание – Seraj Ahmad 6 March 2016 в 09:34

Я понимаю, что это напрямую не отвечает на вопрос super(), но я считаю, что он достаточно релевантен для совместного использования.

Существует также способ прямого вызова каждого унаследованного класса:


class First(object):
    def __init__(self):
        print '1'

class Second(object):
    def __init__(self):
        print '2'

class Third(First, Second):
    def __init__(self):
        Second.__init__(self)

Просто отметьте, что если вы сделаете это так, вам придется вызывать их вручную, так как я уверен, что First __init__() не будет вызываться.

15
ответ дан sfjac 21 August 2018 в 01:17
поделиться
  • 1
    Он не будет вызываться, потому что вы не вызывали каждый унаследованный класс. Проблема скорее в том, что если First и Second наследуют другой класс и называют его напрямую, то этот общий класс (начальная точка алмаза) вызывается дважды. супер избегает этого. – Trilarion 29 July 2014 в 13:04
  • 2
    @Trilarion Yea, я был уверен, что это не так. Тем не менее, я не знал окончательно, и я не хотел заявлять, как если бы я это делал, хотя это было маловероятно. Это хорошая мысль о том, что object вызывается дважды. Я об этом не думал. Я просто хотел сказать, что вы вызываете родительские классы напрямую. – Seaux 30 July 2014 в 19:58
  • 3
    К сожалению, это прерывается, если init пытается получить доступ к любым приватным методам :( – Erik Aronesty 10 May 2018 в 21:29

Еще одна не охваченная точка - это параметры для инициализации классов. Поскольку пункт назначения super зависит от подкласса, единственным хорошим способом передачи параметров является их упаковка. Затем будьте осторожны, чтобы не иметь одинаковое имя параметра с разными значениями.

Пример:

class A(object):
    def __init__(self, **kwargs):
        print('A.__init__')
        super().__init__()

class B(A):
    def __init__(self, **kwargs):
        print('B.__init__ {}'.format(kwargs['x']))
        super().__init__(**kwargs)


class C(A):
    def __init__(self, **kwargs):
        print('C.__init__ with {}, {}'.format(kwargs['a'], kwargs['b']))
        super().__init__(**kwargs)


class D(B, C): # MRO=D, B, C, A
    def __init__(self):
        print('D.__init__')
        super().__init__(a=1, b=2, x=3)

print(D.mro())
D()

дает:

[<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>]
D.__init__
B.__init__ 3
C.__init__ with 1, 2
A.__init__

Вызов суперкласса __init__ непосредственно к более прямому назначению параметров заманчиво, но не удается, если есть какой-либо вызов super в суперклассе и / или изменен MRO, а класс A может быть вызван несколько раз, в зависимости от реализации.

В заключение: совместное наследование и супер и конкретные параметры для инициализации не работают вместе очень хорошо.

10
ответ дан Trilarion 21 August 2018 в 01:17
поделиться

Общий

Предполагая, что все спускается с object (вы сами по себе, если это не так), Python вычисляет порядок разрешения метода (MRO) на основе вашего дерева наследования класса. MRO удовлетворяет 3 свойствам:

  • Дети класса приходят перед своими родителями
  • Левые родители приходят перед правильными родителями
  • Класс появляется только один раз в MRO

Если такой порядок не существует, ошибки Python. Внутренняя работа - это C3-линеризация родословных классов. Подробнее читайте здесь: https://www.python.org/download/releases/2.3/mro/

Таким образом, в обоих приведенных ниже примерах это:

  1. Ребенок
  2. Влево
  3. Вправо
  4. Родитель

Когда метод вызванное, первое вхождение этого метода в MRO - это тот, который вызывается. Любой класс, который не реализует этот метод, пропускается. Любой вызов super внутри этого метода вызовет следующее вхождение этого метода в MRO. Следовательно, это имеет значение как в том порядке, в котором вы размещаете классы в наследовании, так и там, где вы помещаете вызовы в super в методах.

С super сначала в каждом методе

class Parent(object):
    def __init__(self):
        super(Parent, self).__init__()
        print "parent"

class Left(Parent):
    def __init__(self):
        super(Left, self).__init__()
        print "left"

class Right(Parent):
    def __init__(self):
        super(Right, self).__init__()
        print "right"

class Child(Left, Right):
    def __init__(self):
        super(Child, self).__init__()
        print "child"

Child() Выходы:

parent
right
left
child

С super последним в каждом методе

class Parent(object):
    def __init__(self):
        print "parent"
        super(Parent, self).__init__()

class Left(Parent):
    def __init__(self):
        print "left"
        super(Left, self).__init__()

class Right(Parent):
    def __init__(self):
        print "right"
        super(Right, self).__init__()

class Child(Left, Right):
    def __init__(self):
        print "child"
        super(Child, self).__init__()

Child() Выходы:

child
left
right
parent
9
ответ дан Zags 21 August 2018 в 01:17
поделиться
  • 1
    Я вижу, что вы можете получить доступ к Left, используя super() из Child. предположим, что я хочу получить доступ к Right изнутри Child. Есть ли способ получить доступ к Right из Child, используя супер? Или я должен непосредственно называть Right изнутри super? – alpha_989 15 April 2018 в 22:21
  • 2
    @ alpha_989 Если вы хотите получить доступ к методу только определенного класса, вам следует ссылаться только на этот класс, а не на использование супер. Супер - это следование цепочке наследования, а не к методу конкретного класса. – Zags 6 May 2018 в 12:04
Другие вопросы по тегам:

Похожие вопросы: