Das neue magische super()
Verhalten wurde hinzugefügt, um eine Verletzung des DRY-Prinzips (Don't Repeat Yourself) zu vermeiden (siehe PEP 3135) . Wenn Sie die Klasse explizit benennen müssen, indem Sie sie als global bezeichnen, treten dieselben Probleme auf, die Sie bei sich super()
selbst festgestellt haben :
class Foo(Bar):
def baz(self):
return super(Foo, self).baz() + 42
Spam = Foo
Foo = something_else()
Spam().baz() # liable to blow up
Gleiches gilt für die Verwendung von Klassendekoratoren, bei denen der Dekorator ein neues Objekt zurückgibt, das den Klassennamen neu bindet:
@class_decorator_returning_new_class
class Foo(Bar):
def baz(self):
# Now `Foo` is a *different class*
return super(Foo, self).baz() + 42
Die magische super()
__class__
Zelle umgeht diese Probleme, indem sie Ihnen Zugriff auf das ursprüngliche Klassenobjekt gewährt.
Der PEP wurde von Guido ins Leben gerufen, der sich ursprünglich vorstellte super
, ein Schlüsselwort zu werden , und die Idee, eine Zelle zum Nachschlagen der aktuellen Klasse zu verwenden, war auch seine . Die Idee, daraus ein Schlüsselwort zu machen, war sicherlich Teil des ersten Entwurfs des PEP .
Tatsächlich war es jedoch Guido selbst, der sich dann von der Keyword-Idee als "zu magisch" zurückzog und stattdessen die aktuelle Implementierung vorschlug. Er rechnete damit, dass die Verwendung eines anderen Namens super()
ein Problem sein könnte :
Mein Patch verwendet eine Zwischenlösung: Es wird davon ausgegangen, dass Sie diese benötigen, __class__
wenn Sie eine Variable mit dem Namen verwenden 'super'
. Wenn Sie (global) So benennen Sie super
zu supper
und Verwendung supper
aber nicht super
, es wird nicht funktionieren ohne Argumente (aber es wird immer noch funktionieren , wenn Sie übergeben es entweder
__class__
oder das tatsächliche Klassenobjekt); Wenn Sie eine nicht verwandte Variable mit dem Namen haben super
, funktionieren die Dinge, aber die Methode verwendet den etwas langsameren Aufrufpfad, der für Zellenvariablen verwendet wird.
Am Ende war es also Guido selbst, der verkündete, dass sich die Verwendung eines super
Schlüsselworts nicht richtig anfühlte und dass die Bereitstellung einer magischen __class__
Zelle ein akzeptabler Kompromiss war.
Ich stimme zu, dass das magische, implizite Verhalten der Implementierung etwas überraschend ist, aber super()
eine der am häufigsten falsch angewendeten Funktionen in der Sprache ist. Schauen Sie sich einfach alle falsch angewendeten super(type(self), self)
oder super(self.__class__, self)
aufgerufenen Aufrufe im Internet an. Wenn einer dieser Codes jemals von einer abgeleiteten Klasse aufgerufen wurde , würde dies zu einer unendlichen Rekursionsausnahme führen . Zumindest super()
vermeidet der vereinfachte Aufruf ohne Argumente dieses Problem.
Wie für die umbenannten super_
; Referenz nur __class__
in Ihrer Methode als auch und es wird wieder funktionieren. Die Zelle wird erstellt, wenn Sie in Ihrer Methode entweder auf die super
oder auf die __class__
Namen verweisen :
>>> super_ = super
>>> class A(object):
... def x(self):
... print("No flipping")
...
>>> class B(A):
... def x(self):
... __class__ # just referencing it is enough
... super_().x()
...
>>> B().x()
No flipping