Heim  >  Artikel  >  Backend-Entwicklung  >  Der Unterschied zwischen super() und __init__() in Python-Klassen

Der Unterschied zwischen super() und __init__() in Python-Klassen

WBOY
WBOYOriginal
2016-12-05 13:27:141387Durchsuche

Die von super() und __init__() implementierten Funktionen sind bei der Einzelvererbung ä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 Sie bei Verwendung der super()-Vererbung nicht explizit auf die Basisklasse verweisen müssen.

super() kann nur in Klassen neuen Stils verwendet werden

Ändern Sie die Basisklasse in eine Klasse im alten Stil, d. h. erben Sie keine Basisklasse

class Base():
def __init__(self):
print 'Base create'

Bei der Ausführung wird beim Initialisieren von b ein Fehler gemeldet:

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

Super ist nicht die übergeordnete Klasse, sondern die nächste Klasse in der Vererbungssequenz

Im Falle einer Mehrfachvererbung entspricht die Vererbungsreihenfolge super() der Rückgabe der nächsten Klasse in der Vererbungsreihenfolge anstelle der übergeordneten Klasse, ähnlich wie bei dieser Funktion:

def super(class_name, self):
mro = self.__class__.mro()
return mro[mro.index(class_name) + 1]

mro() wird verwendet, um die Vererbungsreihenfolge von Klassen zu ermitteln.

Zum 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__

Die Ausgabeergebnisse lauten wie folgt:

enter A 
enter B 
Base create
leave B
leave A
(<class '__main__.childC'>, <class '__main__.childA'>, <class '__main__.childB'>, <class '__main__.Base'>, <type 'object'>)

supder ist nicht mit der übergeordneten Klasse verbunden, daher ist die Ausführungsreihenfolge A –> B –> –>Basis

Der Ausführungsprozess ist äquivalent zu: Beim Initialisieren von childC() wird zuerst super(childA, self).__init__() im Konstruktor von childA aufgerufen, super(childA, self) kehrt nach childA in der Vererbungssequenz von zurück die aktuelle Klasse A-Klasse childB; dann childB().__init()__ ausführen und in dieser Reihenfolge fortfahren.

Wenn Sie bei der Mehrfachvererbung super(childA, self).__init__() in childA() durch Base.__init__(self) ersetzen, wird nach der Vererbung von childA direkt zur Basisklasse und childB gesprungen wird übersprungen:

enter A 
Base create
leave A
(<class '__main__.childC'>, <class '__main__.childA'>, <class '__main__.childB'>, <class '__main__.Base'>, <type 'object'>)

Wie aus der super()-Methode ersichtlich ist, kann der erste Parameter von super() der Name einer beliebigen Klasse in der Vererbungskette sein,

Wenn es sich selbst ist, erbt es der Reihe nach die nächste Klasse

Wenn es sich um die vorherige Klasse in der Vererbungskette handelt, wird sie unendlich oft wiederholt.

Wenn es sich um eine spätere Klasse in der Vererbungskette handelt, werden die Klassen zwischen der Vererbungskettenzusammenfassung selbst und der eingehenden Klasse ignoriert;

Wenn beispielsweise „super“ in „childA()“ in „super(childC, self).init()“ geändert wird, führt das Programm eine unendliche Rekursion durch.

Zum Beispiel:

File "C:/Users/Administrator/Desktop/crawler/learn.py", line 10, in __init__
super(childC, self).__init__()
File "C:/Users/Administrator/Desktop/crawler/learn.py", line 10, in __init__
super(childC, self).__init__()
File "C:/Users/Administrator/Desktop/crawler/learn.py", line 10, in __init__
super(childC, self).__init__()
File "C:/Users/Administrator/Desktop/crawler/learn.py", line 10, in __init__
super(childC, self).__init__()
File "C:/Users/Administrator/Desktop/crawler/learn.py", line 10, in __init__
super(childC, self).__init__()
File "C:/Users/Administrator/Desktop/crawler/learn.py", line 10, in __init__
super(childC, self).__init__()
File "C:/Users/Administrator/Desktop/crawler/learn.py", line 10, in __init__
super(childC, self).__init__()
File "C:/Users/Administrator/Desktop/crawler/learn.py", line 10, in __init__
super(childC, self).__init__()
File "C:/Users/Administrator/Desktop/crawler/learn.py", line 10, in __init__
super(childC, self).__init__()
File "C:/Users/Administrator/Desktop/crawler/learn.py", line 10, in __init__
super(childC, self).__init__()
File "C:/Users/Administrator/Desktop/crawler/learn.py", line 10, in __init__
super(childC, self).__init__()
File "C:/Users/Administrator/Desktop/crawler/learn.py", line 10, in __init__
super(childC, self).__init__()
File "C:/Users/Administrator/Desktop/crawler/learn.py", line 10, in __init__
super(childC, self).__init__()
RuntimeError: maximum recursion depth exceeded while calling a Python object
super() kann wiederholte Aufrufe vermeiden

Wenn ChildA auf Base basiert, erbt ChildB ChildA und Base, und wenn ChildB die __init__()-Methode von Base aufrufen muss, wird __init__() zweimal ausgeführt:

class Base(object):
def __init__(self):
print 'Base create'
class childA(Base):
def __init__(self):
print 'enter A '
Base.__init__(self)
print 'leave A'
class childB(childA, Base):
def __init__(self):
childA.__init__(self)
Base.__init__(self)
b = childB()
Bases __init__()-Methode wird zweimal ausgeführt

enter A 
Base create
leave A
Base create
Durch die Verwendung von super() können wiederholte Aufrufe vermieden werden

class Base(object):
def __init__(self):
print 'Base create'
class childA(Base):
def __init__(self):
print 'enter A '
super(childA, self).__init__()
print 'leave A'
class childB(childA, Base):
def __init__(self):
super(childB, self).__init__()
b = childB()
print b.__class__.mro()
enter A 
Base create
leave A
[<class '__main__.childB'>, <class '__main__.childA'>, <class '__main__.Base'>, <type 'object'>]
Das Obige ist der vom Herausgeber eingeführte Unterschied zwischen super() und __init__(). Ich hoffe, er wird Ihnen hilfreich sein. Wenn Sie Fragen haben, hinterlassen Sie mir bitte eine Nachricht Sie rechtzeitig. Ich möchte mich auch bei Ihnen allen für Ihre Unterstützung der Script House-Website bedanken!

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