Le nouveau super()
comportement magique a été ajouté pour éviter de violer le principe DRY (Don't Repeat Yourself), voir PEP 3135 . Devoir nommer explicitement la classe en la référençant comme un global est également sujet aux mêmes problèmes de reliure que vous avez découverts avec super()
lui-même:
class Foo(Bar):
def baz(self):
return super(Foo, self).baz() + 42
Spam = Foo
Foo = something_else()
Spam().baz() # liable to blow up
La même chose s'applique à l'utilisation de décorateurs de classe où le décorateur renvoie un nouvel objet, qui relie le nom de la classe:
@class_decorator_returning_new_class
class Foo(Bar):
def baz(self):
# Now `Foo` is a *different class*
return super(Foo, self).baz() + 42
La super()
__class__
cellule magique évite ces problèmes en vous donnant accès à l'objet de classe d'origine.
Le PEP a été lancé par Guido, qui envisageait initialement de super
devenir un mot-clé , et l'idée d'utiliser une cellule pour rechercher la classe actuelle était également la sienne . Certes, l'idée d'en faire un mot-clé faisait partie de la première ébauche du PEP .
Cependant, c'est en fait Guido lui-même qui s'est ensuite éloigné de l'idée de mot-clé comme «trop magique» , proposant plutôt l'implémentation actuelle. Il prévoyait que l'utilisation d'un nom différent pour super()
pourrait être un problème :
Mon patch utilise une solution intermédiaire: il suppose que vous en avez besoin __class__
chaque fois que vous utilisez une variable nommée 'super'
. Ainsi, si vous (globalement) renommer super
à supper
et de l' utilisation supper
mais non super
, cela ne fonctionnera pas sans arguments (mais cela fonctionnera si vous passez soit
__class__
ou l'objet de classe réelle); si vous avez une variable non liée nommée super
, les choses fonctionneront mais la méthode utilisera le chemin d'appel légèrement plus lent utilisé pour les variables de cellule.
Donc, à la fin, c'est Guido lui-même qui a proclamé que l'utilisation d'un super
mot-clé ne se sentait pas bien, et que fournir une __class__
cellule magique était un compromis acceptable.
Je conviens que le comportement magique et implicite de l'implémentation est quelque peu surprenant, mais super()
c'est l'une des fonctions les plus mal appliquées du langage. Jetez un œil à toutes les invocations mal appliquées super(type(self), self)
ou super(self.__class__, self)
trouvées sur Internet; si l'un de ces codes était appelé à partir d'une classe dérivée, vous vous retrouveriez avec une exception de récursivité infinie . À tout le moins, l' super()
appel simplifié , sans arguments, évite ce problème.
Quant à la renommée super_
; simplement référence __class__
dans votre méthode aussi bien et ça va fonctionner à nouveau. La cellule est créée si vous référencez les noms super
ou __class__
dans votre méthode:
>>> 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