Erklärung zum Unterschied zwischen super() und __init__() in Python-Klassen

高洛峰
Freigeben: 2017-03-16 16:08:29
Original
1376 Leute haben es durchsucht

Wenn Single erbt, sind die von super() und init() implementierten Funktionen ähnlich

class Base(object):
    def init(self):
        print 'Base create'
class childA(Base):
    def init(self):
        print 'creat A ',
        Base.init(self)
class childB(Base):
    def init(self):
        print 'creat B ',
        super(childB, self).init()
base = Base()
a = childA()
b = childB()
Nach dem Login kopieren

Ausgabeergebnis:

Base create
creat A  Base create
creat B  Base create
Nach dem Login kopieren

Der Unterschied besteht darin, dass bei Verwendung der super()-Vererbung keine explizite Referenz auf die -Basisklasse erforderlich ist.


super() kann nur in Klassen neuen Stils verwendet werden


Ändern Sie die Basisklasse in eine Klasse im alten Stil, das heißt, sie erbt keine Basisklasse. Wenn

class Base():
    def init(self):
        print 'Base create'
Nach dem Login kopieren

ausgeführt wird, wird beim Initialisieren von b ein Fehler gemeldet:

super(childB, self).init()
TypeError: must be type, not classobj
Nach dem Login kopieren


super ist keine übergeordnete Klasse. Stattdessen wird die nächste Klasse in der Vererbungssequenz


die Vererbungssequenz in die Mehrfachvererbung einbeziehen. entspricht der Rückgabe der nächsten Klasse in der Vererbungssequenz, nicht der übergeordneten Klasse. Eine Funktion ähnlich dieser:

def super(class_name, self):
    mro = self.class.mro()
    return mro[mro.index(class_name) + 1]
Nach dem Login kopieren

mro() wird verwendet, um die Vererbungsreihenfolge einer Klasse zu ermitteln. Beispiel:

class Base(object):
    def init(self):
        print 'Base create'
class childA(Base):
    def init(self):
        print 'enter A '
        # Base.init(self)
        super(childA, self).init()
        print 'leave A'
class childB(Base):
    def init(self):
        print 'enter B '
        # Base.init(self)
        super(childB, self).init()
        print 'leave B'
class childC(childA, childB):
    pass
c = childC()
print c.class.mro
Nach dem Login kopieren

Das Ausgabeergebnis lautet wie folgt:

enter A 
enter B 
Base create
leave B
leave A
(<class &#39;main.childC&#39;>, <class &#39;main.childA&#39;>, <class &#39;main.childB&#39;>, <class &#39;main.Base&#39;>, <type &#39;object&#39;>)
Nach dem Login kopieren

supder ist nicht mit der übergeordneten Klasse verknüpft, daher ist die Ausführungsreihenfolge A —> B—> —>Base


Der Ausführungsprozess entspricht: beim Initialisieren von childC(), super(childA, self).init() in der Konstruktormethode< von childA 🎜> wird zuerst aufgerufen, super(childA, self) gibt eine Klasse childB nach childA in der Vererbungsreihenfolge der aktuellen Klasse zurück, führt dann childB().init() aus und die Sequenz wird fortgesetzt.


Wenn Sie bei der Mehrfachvererbung während der Ausführung super(childA, self).init() in childA() durch Base._init_(self) ersetzen, Nach der Vererbung von childA , springt es direkt zur Basisklasse und überspringt childB:

enter A 
Base create
leave A
(<class &#39;main.childC&#39;>, <class &#39;main.childA&#39;>, <class &#39;main.childB&#39;>, <class &#39;main.Base&#39;>, <type &#39;object&#39;>)
Nach dem Login kopieren
Wie aus der super()-Methode ersichtlich ist, kann der erste Parameter von super() ein beliebiger Name in der Vererbungskette sein eine Klasse,


, wenn sie sie selbst ist, erbt sie der Reihe nach die nächste Klasse


, wenn sie es ist ist eine Vererbungskette. Die Klassen davor sind

rekursiv auf unbestimmte Zeit;


Wenn es sich um eine Klasse nach der Vererbungskette handelt, wird die Vererbungskette selbst zusammengefasst und Die eingehende Klasse wird ignoriert. Wenn zum Beispiel super in childA() in super(childC, self).init() geändert wird, wird Das Programm wird unendlich oft rekursiv ausgeführt. Beispiel:


super() kann wiederholte Aufrufe von

  File "test.py", line 12, in init
    super(childC, self).init()
  File "test.py", line 12, in init
    super(childC, self).init()
  File "test.py", line 12, in init
    super(childC, self).init()
  File "test.py", line 12, in init
    super(childC, self).init()
  File "test.py", line 12, in init
    super(childC, self).init()
  File "test.py", line 12, in init
    super(childC, self).init()
  File "test.py", line 12, in init
    super(childC, self).init()
  File "test.py", line 12, in init
    super(childC, self).init()
  File "test.py", line 12, in init
    super(childC, self).init()
RuntimeError: maximum recursion depth exceeded while calling a Python object
Nach dem Login kopieren


vermeiden, wenn childA auf Base basiert , childB erbt childA Wenn childB mit Base die init()-Methode von Base aufrufen muss, führt dies dazu, dass init() zweimal ausgeführt wird:

Bases init()-Methode wird zweimal ausgeführt

class Base(object):
    def init(self):
        print &#39;Base create&#39;
class childA(Base):
    def init(self):
        print &#39;enter A &#39;
        Base.init(self)
        print &#39;leave A&#39;
class childB(childA, Base):
    def init(self):
        childA.init(self)
        Base.init(self)
b = childB()
Nach dem Login kopieren

Mit super() können wiederholte Aufrufe vermieden werden

enter A 
Base create
leave A
Base create
Nach dem Login kopieren


Das obige ist der detaillierte Inhalt vonErklärung zum Unterschied zwischen super() und __init__() in Python-Klassen. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Verwandte Etiketten:
Quelle:php.cn
Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage