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
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()
enter A Base create leave A Base create
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'>]