#python #multiple-inheritance
#python #множественное наследование
Вопрос:
Я читал эту статью, но не могу понять следующий пример:
class Class1:
def m(self):
print("In Class1")
print("here1")
class Class2(Class1):
def m(self):
print("In Class2")
super().m()
print("here2")
class Class3(Class1):
def m(self):
print("In Class3")
super().m()
print("here3")
class Class4(Class2, Class3):
def m(self):
print("In Class4")
super().m()
obj = Class4()
obj.m()
Результатом является:
In Class4
In Class2
In Class3
In Class1
here1
here3
here2
Почему результат печатается в таком порядке? Я ожидал, что результат будет:
In Class4
In Class2
In Class1
here1
here2
In Class3
In Class1
here1
here3
Почему super().m()
отбрасывается при вводе Class2
? он запускается только тогда, когда мы заканчиваем печать «В Class3».
Спасибо
Комментарии:
1. Учитывая результат, который вы видите, вы должны быть в состоянии определить для себя порядок, в котором выполняется программа.
2. @quamrana Почему такой порядок? разве программа не должна запускать метод суперкласса всякий раз, когда он достигает super().m() ? это происходит только один раз и в конце программы
3. Связанная статья не вдается в подробности, но это поведение контролируется с помощью правил Python «Порядок разрешения метода» (MRO). Эта ссылка содержит несколько более подробных примеров и объяснений. По сути,
super()
это не означает «вызвать этот метод из родительского класса», а скорее: «вызвать этот метод из следующего класса в MRO».4. @0x5453 Это имеет смысл. Я не знал, что это так работает. Спасибо
Ответ №1:
Это из-за порядка разрешения метода Python. Вы можете просмотреть MRO ваших классов, вызвав Class4.mro()
, например. Вы увидите, что Class3
это происходит раньше Class1
. Это потому, что MRO Python (https://www.python.org/download/releases/2.3/mro /) использует алгоритм линеаризации C3 (https://en.wikipedia.org/wiki/C3_linearization ).
Цитирование Гвидо ван Россума (из Википедии):
По сути, идея C3 заключается в том, что если вы запишете все правила упорядочения, налагаемые отношениями наследования в сложной иерархии классов, алгоритм определит монотонный порядок классов, который удовлетворяет всем из них. Если такой порядок не может быть определен, алгоритм завершится с ошибкой.
Вы можете ознакомиться с алгоритмом, но упрощенный взгляд, которого я хотел бы придерживаться в отношении алогичности, заключается в следующем: по сути, это DFS слева направо, но подкласс всегда будет раньше, чем суперкласс.
Примечание: это упрощенный взгляд на правило, и он не охватывает ни алгоритм, ни неудачные случаи, но в большинстве случаев это хороший способ запомнить основы MRO.
Ответ №2:
Сначала он выводит порядок расположения всех классов, потому что вы вызываете этот суперкласс
def m(self):
print("In Class3")
super().m()
print("here3")
Смотрите, вы вызываете super().m(), что приведет к запуску функции self родительских классов, которая содержит оператор print(«In Classn») в этой функции, который затем вызовет следующий super().m(), вызывающий запуск другой функции self. Вам нужно распечатать здесь, прежде чем вручную.
Комментарии:
1. Мой вопрос в том, почему мы не запускаем метод Class1 m при вызове super().m() из Class2? в соответствии с результатом, мы запускаем метод Class1 m только один раз и после того, как в Class2 и в Class 3 будут напечатаны