К какому родительскому методу Third относится super().__init__? Могу ли я выбрать, какой из них выполняется?
Я знаю, что это как-то связано с порядком разрешения метода (MRO).
Переведено автоматически
Ответ 1
Это описано с достаточным количеством деталей самим Гвидо в его сообщении в блоге Порядок разрешения метода (включая две предыдущие попытки).
В вашем примере Third() вызовет First.__init__. Python ищет каждый атрибут в родительском классе, поскольку они перечислены слева направо. В данном случае мы ищем __init__. Итак, если вы определяете
classThird(First, Second): ...
Python начнет с поиска в First, и, если у First нет атрибута, то он будет искать в Second.
Эта ситуация усложняется, когда пути наследования начинают пересекаться (например, если First унаследовано от Second). Прочитайте ссылку выше для получения более подробной информации, но, в двух словах, Python попытается поддерживать порядок, в котором каждый класс отображается в списке наследования, начиная с самого дочернего класса.
Кстати: если Python не может найти согласованный порядок разрешения метода, он вызовет исключение, вместо того чтобы вернуться к поведению, которое может удивить пользователя.
Должно Third быть MRO [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. И он построен так, как я объяснил:
Ваш код и другие ответы содержат ошибки. В них отсутствуют super() вызовы в первых двух классах, которые необходимы для работы совместного подкласса. Лучше, если:
super() Вызов находит следующий метод в MRO на каждом шаге, поэтому First и Second он тоже должен быть, иначе выполнение останавливается в конце Second.__init__().
Безsuper() вызовов в First и Second вывод отсутствует second:
>>> Third() first third
Ответ 3
Я хотел немного уточнить ответ lifeless, потому что, когда я начал читать о том, как использовать super () в иерархии множественного наследования в Python, я не сразу понял это.
Что вам нужно понимать, так это то, что super(MyClass, self).__init__() предоставляет метод next__init__ в соответствии с используемым алгоритмом упорядочения разрешения методов (MRO) в контексте полной иерархии наследования.
Эта последняя часть имеет решающее значение для понимания. Давайте еще раз рассмотрим пример:
Алгоритм MRO был улучшен начиная с Python 2.3, чтобы хорошо работать в сложных случаях, но я предполагаю, что использование "обхода слева направо в глубину" + "ожидаемое удаление дубликатов последним" все еще работает в большинстве случаев (пожалуйста, прокомментируйте, если это не так). Обязательно прочтите сообщение в блоге Guido!
Ответ 4
Это известно как проблема с бриллиантами, на странице есть запись на Python, но, короче говоря, Python будет вызывать методы суперкласса слева направо.