Страницы

Поиск по вопросам

четверг, 9 января 2020 г.

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

#python #наследование #множественное_наследование


Копипаст из idle

class A(object):
    def go(self):
        print("go A go!")
    def stop(self):
        print("stop A stop!")
    def pause(self):
        raise Exception("Not Implemented")

class B(A):
    def go(self):
        super(B, self).stop()
        print("go B go!")


class C(A):
    def go(self):
        super(C, self).go()
        print("go C go!")
    def stop(self):
        super(C, self).stop()
        print("stop C stop!")


class E(B,C): pass

e=E()


e.go() вывел

stop A stop!
stop C stop!
go B go!


Непонятно откуда такой вывод
    


Ответы

Ответ 1



Сначала немного теории: Когда вы дёргаете метод у объекта, интерпретатор пытается найти этот метод сначала у самого объекта, если не находит - то ищет у класса объекта, если и там не находит, то по очереди обходит всех предков класса, пока не найдёт. Порядок обхода предков при множественном наследовании определяется алгоритмом MRO C3. Хорошая статья об этом есть на Хабре: https://habr.com/ru/post/62203/ Для вашего класса E в соответствии с MRO C3 порядок обхода родителей будет таким: E -> B -> C -> A -> object В этом легко убедиться так: print(E.__mro__) Теперь по пунктам, что происходит в вашем коде: Вы дёргаете для объекта e метод go Интерпретатор ищёт go в e. Не находит. Ищет go в классе E. Не находит. Ищет go в классе B. Находит, начинает исполнять. Ему нужно выполнить super(B, self).stop() Так как в данном случае self - это e (то есть объект класса E), то он будет делать обход в соответствии с порядком B -> C -> A. И, следовательно, будет искать stop не среди предков класса B, а в следующем по цепочке классе C. В C метод stop есть, но в нём делается сначала super(C, self).stop() поэтому интерпретатор пойдёт в A.stop В A.stop он напечатает "stop A stop!", после чего вернётся в C.stop В C.stop он напечатает "stop C stop!", после чего вернётся в B.go В B.go он напечатает "go B go!" Вот и всё :)

Комментариев нет:

Отправить комментарий