Hinweis: Hier wird Python 3 als Betriebsumgebung verwendet und das Beispiel stammt aus Kapitel 8 des „Python-Kochbuchs“.
Wenn eine Unterklasse in Python die übergeordnete Klasse initialisieren möchte, gibt es zwei Hauptmethoden: Die erste besteht darin, den Namen der übergeordneten Klasse direkt zu übergeben, und die zweite darin, die Supermethode zu verwenden. Bei der Einzelvererbung gibt es keinen Unterschied zwischen den beiden, bei der Mehrfachvererbung gibt es jedoch einige subtile Unterschiede, die beachtet werden müssen. Beispielerklärung ist das letzte Wort!
1. Bei Verwendung des übergeordneten Klassennamens:
Python-Code
Klassenbasis:
def __init__(self):
print('Base.__init__')
class A(Base):
def __init__(self):
Base.__init__(self)
print('A.__init__')
class B(Base):
def __init__(self):
Base.__init__(self)
print('B.__init__')
class C(A,B):
def __init__(self ):
A.__init__(self)
B.__init__(self)
print('C.__init__')
This Bei der Instanziierung der C-Klasse sieht die Ausgabe wie folgt aus:
Python-Code
>>> c = C()
Base.__init__
A.__init__
Base.__init__
B.__init__
C.__init__
>>> >
Es ist ersichtlich, dass die Basisklasse zweimal aufgerufen wird. Dies dürfte in vielen Fällen nicht das gewünschte Ergebnis sein, daher können wir zu diesem Zeitpunkt die Verwendung der Super-Methode in Betracht ziehen.
2. Bei Verwendung von super:
Zu diesem Zeitpunkt lautet die Ausgabe der Instanziierung der Klasse C:
Python-Code >>> c = C()Base.__init__
B.__init__
A.__init__
C.__init__
>>> 🎜>
Sie können die Basis sehen. Wird die Klasse nur einmal aufgerufen? Aber leider hat mich das nicht dazu bewogen, diesen Blog-Eintrag zu schreiben, denn wenn Sie genau hinsehen, ist Ihnen aufgefallen, dass „B.__init__“ zuerst ausgegeben wird, obwohl die Basisklasse wie erwartet nur einmal aufgerufen wird, und dann „Einfach ausgeben“ A.__init__"? Und warum führt dies dazu, dass Base nur einmal initialisiert wird? Du bist bestimmt auch etwas verwirrt, oder? Tatsächlich muss all dies dem aufrufenden Prozess von super während der Mehrfachvererbung zugeschrieben werden. Wenn Python eine Klasse implementiert (nicht nur Vererbung), generiert es eine Methode zum Generieren einer Analysereihenfolgeliste, die über das Klassenattribut __mro__ angezeigt werden kann, wie in diesem Beispiel:Python-Code
>>> C.__mro__
(
>>>
Bei der Suche nach einer Eigenschaft oder Methode wird also jede Klasse gemäß dieser Liste durchlaufen, bis die erste Klasse gefunden wird, die dieser Eigenschaft oder Methode entspricht. Wenn Super bei der Vererbung verwendet wird, sucht der Interpreter jedes Mal, wenn er auf Super trifft, nach der nächsten Klasse in der Liste, bis er nicht mehr auf Super trifft oder die Liste durchlaufen wird, und kehrt dann Schicht für Schicht zurück, ähnlich wie bei der Rekursion. Daher ist der Suchvorgang in diesem Beispiel: Super in C finden -> Suche nach der nächsten Klasse in der Liste, also A -> Super erneut in A finden, nach B suchen -> Super erscheint wieder in B, search Base -> Initialisieren Sie die Base-Klasse und kehren Sie rekursiv zurück.
Um den Vorgang besser zu erklären, kommentieren Sie jetzt bitte die Superzeile der Klasse B aus:
Python-Code
Klasse B(Basis):
def __init__(self):
#super().__init__()
print('B.__init__')
class C( A,B):
def __init__(self):
super().__init__() # Nur ein Aufruf von super() hier
print('C. __init__')
Klasse C erneut instanziieren, die Ausgabe ist wie folgt:
Pythonn-Code
>>> )
B.__init__
A.__init__
C.__init__
Basisklasse erzeugt keine Ausgabe mehr! Warum? Da es in B kein Super gibt, kann die Liste nicht nach der Basisklasse suchen, sodass Base nicht initialisiert wird!