11.1 Method Resolution Order
Die Method Resolution Order (MRO) bestimmt die Reihenfolge, in der Python nach Methoden und Attributen in der Klassenhierarchie sucht. Das ist besonders wichtig bei Mehrfachvererbung, wenn eine Klasse Attribute und Methoden von mehreren Elternklassen erben kann.
Einfach gesagt, gibt es eine strikte feste Reihenfolge (oder eher Algorithmus), nach der Python den Vererbungsbaum der Klassen durchläuft. Dieser Algorithmus stellt die korrekte Reihenfolge der Methodensuche sicher und kann wie folgt beschrieben werden:
C3-Linearisation-Algorithmus
Der C3-Linearisation-Algorithmus bestimmt die MRO durch Kombination von:
- Der Klasse selbst.
- Der Liste der Elternklassen in der Reihenfolge, in der sie aufgelistet sind.
- MRO der Elternklassen in der gleichen Reihenfolge.
Regeln des C3-Linearisation-Algorithmus
- Lokale Methodensortierung beibehalten: Wenn Klasse
Avor KlasseBangegeben ist, müssen alle Methoden von KlasseAvor den Methoden von KlasseBbetrachtet werden. - Reihenfolge in Elternklassen beibehalten: Wenn Klasse
Adie Elternklasse von KlasseBist, müssen alle Methoden von KlasseAvor den Methoden von KlasseBbetrachtet werden. - Vererbungsreihenfolge beachten: Wenn Klasse
CElternklasse für zwei oder mehr Klassen ist, sollte die Reihenfolge der Methoden der KlasseCin der MRO aller dieser Klassen beibehalten werden.
Schritte des Algorithmus:
Schritt 1. Wir beginnen mit der Klasse selbst:
Wir beginnen immer mit der Klasse, in der die Methode aufgerufen wird.
Schritt 2. Füge die Basisklassen in der Reihenfolge ihrer Auflistung hinzu:
Nach der aktuellen Klasse überprüfen wir die Basisklassen in der Reihenfolge, in der sie vererbt werden.
Schritt 3. Durchsuche die Elternklassen:
Suche dort nach Feldern und Methoden.
Schritt 4. Kombiniere MRO der Elternklassen:
Wenn dieselbe Basisklasse über mehrere Wege vererbt wird, wird sie nur einmal und in der richtigen Reihenfolge überprüft (alle weiteren Male wird sie übersprungen).
Für diejenigen, die mit dem Thema „Algorithmen und Datenstrukturen“ vertraut sind, ist dies eine Tiefensuche, keine Breitensuche.
11.2 Überprüfung der MRO
In Python kann man die Reihenfolge der Methoden- und Feldsuche einer Klasse überprüfen, indem man das Attribut __mro__ oder die Funktion mro() benutzt.
Beispiel:
class A:
def method(self):
print("A")
class B(A):
def method(self):
print("B")
class C(A):
def method(self):
print("C")
class D(B, C):
def method(self):
print("D")
# Überprüfung der MRO
print(D.__mro__)
Die Ausgabe wird sein:
(<class '__main__.D'>,
<class '__main__.B'>,
<class '__main__.C'>,
<class '__main__.A'>,
<class 'object'>)
Dies zeigt die Reihenfolge, in der Python nach Methoden und Attributen sucht:
D: Python überprüft zuerst die Methode in der KlasseD.-
B: Dann überprüft Python die Methode in der KlasseB(die erste Elternklasse). -
C: Wenn die Methode inBnicht gefunden wird, überprüft Python die Methode inC(die zweite Elternklasse). -
A: Wenn die Methode in den KlassenBundCnicht gefunden wird, überprüft Python die Methode inA. -
object: Am Ende überprüft Python die Methode in der Basisklasseobject.
11.3 Verwendung von super() mit MRO
Die Funktion super() folgt der MRO, um Methoden der Elternklassen in der richtigen Reihenfolge aufzurufen. Schauen wir uns ein Beispiel für die Verwendung von
super() an:
class A:
def method(self):
print("A")
super().method()
class B(A):
def method(self):
print("B")
super().method()
class C(A):
def method(self):
print("C")
super().method()
class D(B, C):
def method(self):
print("D")
super().method()
d = D()
d.method()
Das Ergebnis wird wie folgt aussehen:
D
B
C
A
Reihenfolge der Methode (MRO)
1. Aufruf der Methode method in Klasse D:
- Python überprüft zuerst die Methode in der Klasse
Dund findet sie dort. - Die Methode
D.method()wird ausgeführt und druckt"D". - Dann wird
super().method()aufgerufen, welches der MRO folgt, um die nächste Methode aufzurufen.
2. Aufruf der Methode method in Klasse B:
- Nach der MRO ist die nächste Klasse nach
Ddie KlasseB. - Die Methode
B.method()wird ausgeführt und druckt"B". - Dann wird
super().method()aufgerufen, welches der MRO folgt, um die nächste Methode aufzurufen.
3. Aufruf der Methode method in Klasse C:
- Die nächste Klasse in der MRO nach
BistC. - Die Methode
C.method()wird ausgeführt und druckt"C". - Dann wird
super().method()aufgerufen, welches der MRO folgt, um die nächste Methode aufzurufen.
4. Aufruf der Methode method in Klasse A:
- Die nächste Klasse in der MRO nach
CistA. - Die Methode
A.method()wird ausgeführt und druckt"A". - Dann wird
super().method()aufgerufen, doch daAkeine Elternmethodenmethodhat (außerobject), endet der Aufruf ohne weitere Aktionen.
GO TO FULL VERSION