Множественное наследование — наследование в классе-потомке атрибутов сразу нескольких родительских классов.
Линеаризация в Python — это очерёдность, при которой производится поиск указанного атрибута сначала в классах-потомков, а затем и в родительских классах.
Рассмотрим простые примеры множественного наследования и линеаризации в Python-3.
Множественное наследование и линеаризация при данном процессе в Python 3 показана на примерах ниже. При указании методов с одинаковым названием у разных классов и разным содержимым наследуется в классе-потомке тот, класс которого прописан первым при множественном наследовании (в круглых скобках после названия класса-потомка). Это просто проверить на примере ниже, меняя последовательность расположения родительских классов для наследования у дочернего класса Child.
Множественное наследование в Python 3
class Parent(): def parent_method(self): print("First parent class") class Parent2(): def parent_method(self): print("Second parent class") class Parent3(): def parent_method(self): print("Third parent class") class Child(Parent2, Parent, Parent3): def child_method(self): print("The child method") child=Child() child.parent_method()
Если же каждый метод родительских классов назвать разными названиями, то на примере класса-потомка можно чётко увидеть, что в классе потомке наследуются все родительские методы сразу трёх классов. Получается множественное наследование.
class Parent(): def parent_method(self): print("First parent class") class Parent2(): def parent_method2(self): print("Second parent class") class Parent3(): def parent_method3(self): print("Third parent class") class Child(Parent2, Parent, Parent3): def child_method(self): print("The child method") child=Child() child.parent_method() child.parent_method2() child.parent_method3()
Линеаризация в Python-3
Линеаризация в Python-3 несколько отличается от данного процесса в Python-2. В третьей версии MRO (Method Resolution Order) в наследовании класса-потомка соблюдается порядок следования родительских классов, что было и в их очерёдности при его объявлении. Сначала поиск ведётся в первом объявленном классе-родителе, затем во втором и так далее. Наглядно это увидеть можно в примере ниже. Второй родительский класс наследует метод первого, а класс-потомок наследует второй и третий родительский класс. При вызове класса потомка метод он возьмёт третьего класса. А при вызове второго класса, выведется метод первого.
Такая линеаризация строится для классов нового типа.
print(Child.mro()) выведет информацию как происходила линеаризация, её очерёдность. Сначала метод, к которому обращаются, ищется в классе-потомке, а затем в родительских классах в порядке очереди.
class Parent(): def parent_method(self): print("First parent class") class Parent2(Parent): pass class Parent3(Parent): def parent_method(self): print("Third parent class") class Child(Parent2, Parent3): def child_method(self): print("The child method") parent2=Parent2() parent2.parent_method() child=Child() child.parent_method() print(Child.mro())
Линеаризация в Python-2
Для классов старого типа в Python-2 поиск атрибутов для наследования ведётся в глубину (что отличается от линеаризации классов нового типа), что может привести в итоге к некорректным результатам. Это следует учитывать при программировании в разных версиях Питона.
Использовать множественное наследование следует с особой внимательностью, чтобы избежать путаницы и ошибок в коде.