Heim  >  Artikel  >  Backend-Entwicklung  >  Erklärung zum Unterschied zwischen super() und __init__() in Python-Klassen

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

高洛峰
高洛峰Original
2017-03-16 16:08:291372Durchsuche

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()

Ausgabeergebnis:

Base create
creat A  Base create
creat B  Base create

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'

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

super(childB, self).init()
TypeError: must be type, not classobj


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]

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

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;>)

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 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;>)
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


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()

Mit super() können wiederholte Aufrufe vermieden werden

enter A 
Base create
leave A
Base create


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!

Stellungnahme:
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