Wielokrotne dziedziczenie — możliwość klasy dziedziczenia od kilku klas nadrzędnych jednocześnie — pojawiło się w Pythonie na podstawie innych języków OOP (np. C++), gdzie pomaga w tworzeniu wielokrotnego użytku mixinów. Opracowanie mechanizmu wyszukiwania metod (MRO) zajęło dużo czasu, aby zapewnić przewidywalność w przypadku kolizji metod.
Klasa może otrzymywać metody o tej samej nazwie z różnych klas bazowych. Jak określić, którą metodę zastosować przy jej wywołaniu? Bez jasnej schemy prowadzi to do trudnych do wykrycia błędów.
Python wdraża algorytm MRO (C3 linearization), który określa ścisłą kolejność wyszukiwania metod przy rozwiązywaniu konfliktów w hierarchii. Wszystko staje się przezroczyste, jeśli używasz funkcji super() i metody __mro__ klas do analizy łańcucha dziedziczenia.
Przykład kodu:
class A: def foo(self): print("A") class B(A): def foo(self): print("B") super().foo() class C(A): def foo(self): print("C") super().foo() class D(B, C): def foo(self): print("D") super().foo() D().foo() print(D.__mro__)
Kluczowe cechy:
__mro__;Co się stanie, jeśli nazwy metod rodziców będą identyczne?
Odpowiedź: Wywołanie metody będzie następować w kolejności określonej przez MRO. Pierwsza znaleziona metoda o wymaganej nazwie w łańcuchu — ta zadziała.
Czy można używać super() bez jawnego przekazania self?
Odpowiedź: W Pythonie 3 — tak, wywołanie super().method() w ciele metody klasy jest równoważne z jawnym super(Klasa, self).method(), ale tylko wewnątrz klasy.
Czy można zmienić kolejność MRO istniejącej klasy?
Odpowiedź: Kolejność MRO jest statyczna po zadeklarowaniu klasy, ale można ją badać (lub zbudować nową klasę z inną kolejnością dziedziczenia).
W projekcie stworzono dwa mixiny z podobną metodą, klasa dziedzicząca używa obu mixinów, ale wywołuje metody bezpośrednio przez nazwę klasy, zakłócając kolejność wydarzeń.
Zalety:
Wady:
Używają super() w każdej metodzie mixinów, co gwarantuje wywołanie w łańcuchu, a nie pominięcie potrzebnego zachowania.
Zalety:
Wady: