Also folgte ich Pythons Super Considered Harmful und ging, um seine Beispiele zu testen.
Jedoch Beispiel 1-3 , die die richtige Art und Weise des Aufrufs zeigen , sollte super
beim Umgang mit __init__
Methoden , die unterschiedlichen Argumente erwarten, flat-out funktioniert nicht.
Das bekomme ich:
~ $ python example1-3.py
MRO: ['E', 'C', 'A', 'D', 'B', 'object']
E arg= 10
C arg= 10
A
D arg= 10
B
Traceback (most recent call last):
File "Download/example1-3.py", line 27, in <module>
E(arg=10)
File "Download/example1-3.py", line 24, in __init__
super(E, self).__init__(arg, *args, **kwargs)
File "Download/example1-3.py", line 14, in __init__
super(C, self).__init__(arg, *args, **kwargs)
File "Download/example1-3.py", line 4, in __init__
super(A, self).__init__(*args, **kwargs)
File "Download/example1-3.py", line 19, in __init__
super(D, self).__init__(arg, *args, **kwargs)
File "Download/example1-3.py", line 9, in __init__
super(B, self).__init__(*args, **kwargs)
TypeError: object.__init__() takes no parameters
Es scheint, dass object
selbst eine der im Dokument erwähnten Best Practices verletzt wird, nämlich die Methoden, die verwenden super
müssen *args
und **kwargs
.
Offensichtlich hat Mr. Knight erwartet, dass seine Beispiele funktionieren. Wurde dies in den letzten Versionen von Python geändert? Ich habe 2.6 und 2.7 überprüft und es schlägt bei beiden fehl.
Was ist der richtige Weg, um mit diesem Problem umzugehen?
object
, und sie stellt sicher, dass dieobject
Aufrufe__init__
korrekt sind.__init__
on imobject
Hintergrund alle Parameter in Python 2.5 ignoriert. Dies hat sich in Python 2.6 geändert.Antworten:
Manchmal haben zwei Klassen einige gemeinsame Parameternamen. In diesem Fall können Sie die Schlüssel-Wert-Paare nicht
**kwargs
entfernen oder entfernen*args
. Stattdessen können Sie eineBase
Klasse definieren , die im Gegensatz zuobject
Argumenten Argumente absorbiert / ignoriert:ergibt
Beachten Sie, dass dies
Base
die vorletzte Klasse in der MRO sein muss , damit dies funktioniert .quelle
Base
anrufensuper(Base, self).__init__()
?Base
muss am Ende der MRO kommen (außer fürobject
). Anrufenobject.__init__
bewirkt nichts, daher ist es in Ordnung, nicht anzurufensuper(Base, self).__init__()
. Tatsächlich denke ich, dass es klarer sein kann,super(Base, self).__init__()
den Punkt, derBase
das Ende der Linie ist, nicht einzubeziehen, um nach Hause zu fahren .Wenn Sie viel Vererbung haben werden (das ist hier der Fall), empfehle ich Ihnen, alle Parameter mit
**kwargs
und dannpop
direkt nach der Verwendung zu übergeben (es sei denn, Sie benötigen sie in der Oberschicht).Dies ist der einfachste Weg, um diese Art von Problemen zu lösen.
quelle
Wie in Pythons super () als super erklärt , besteht eine Möglichkeit darin, die Klasse die erforderlichen Argumente essen zu lassen und den Rest weiterzugeben. Wenn die Aufrufkette erreicht ist
object
, wurden alle Argumente verzehrt undobject.__init__
werden (wie erwartet) ohne Argumente aufgerufen. Ihr Code sollte also folgendermaßen aussehen:quelle
E(arg = 10)
? Ich mag diese Methode nicht, ich muss den MRO im Voraus kennen, um sie verwenden zu können. Die andere Methode, bei der ich eine "Stammklasse" schreibe, von der erbt,object
scheint viel sauberer zu sein.super
, daher könnte dieser Ansatz tatsächlich eher theoretisch sein.