Вызов супер метода множественного наследования Python

#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 будут напечатаны