Nom de classe codé en dur passé à super
Le
Alex Marandon
Bonjour,
Tous les exemples d'utilisation de super que j'ai rencontrés passent la
classe appellante en la nommant explicitiment: super(C, self).methode()
Est-ce juste une convention ou bien y a-t-il une raison technique ?
Pourquoi ne pas utiliser super(self.__class__, self).method() à la place
? De cette manière, si on renommait la classe on aurait pas à modifier
aussi l'appel à super.
Merci,
Alex
Tous les exemples d'utilisation de super que j'ai rencontrés passent la
classe appellante en la nommant explicitiment: super(C, self).methode()
Est-ce juste une convention ou bien y a-t-il une raison technique ?
Pourquoi ne pas utiliser super(self.__class__, self).method() à la place
? De cette manière, si on renommait la classe on aurait pas à modifier
aussi l'appel à super.
Merci,
Alex

Poser une question


Ah, mais c'est que ça ne marche pas (sinon super() l'aurait déjà fait).
si on prend l'exemple suivant:
class A(object):
def f(self):
print "A.f()"
class B(A):
def f(self):
print "B.f()"
super(B, self).f()
class C(B):
pass
x = C()
x.f()
Cela imprime "B.f()" puis "A.f()", et tout est normal.
Essaie maintenant de remplacer
super(B, self).f()
par
super(self.__class__, self).f()
et boum, un bel appel en boucle qui se brise sur le mur de la récursion.
La raison, c'est que même à l'intérieur de la fonction B.f,
self.__class__ == C, et donc super() commence par chercher dans B (la
classe qui suit C dans la liste des bases)
Ce qui compte pour super(), ce n'est pas la classe de l'objet, mais la
classe qui contient le code de la méthode. Il faut donc bien indiquer
l'objet classe.
Cela peut poser des problèmes, en particulier si la classe B est
redéfinie. C'est pour cela que python 3.0 (qui sort mercredi!) a trouvé
la parade:
class B(A):
def f(self):
super().f()
C'est presque magique: chaque méthode définit une variable cachée
('__class__') qui représente la classe qui contient la fonction. On y
ajoute le premier paramètre de la fonction, et voilà enfin un vrai super().
--
Amaury Forgeot d'Arc
Il y a une raison technique. super() doit savoir à partir d'où (dans le
mro) il est appelé pour effectuer une résolution correcte (en d'autres
termes : pour savoir à quel position on se situe dans le mro au moment
de l'appel). Il lui faut donc la classe _dans laquelle la méthode est
définie_, et non la classe de l'instance sur laquelle la méthode est
appelée.
Parce que dans ce cas, la résolution ne sera correcte que si
self.__class__ est la classe dans laquelle method est définie.
class Parent(object):
def method(self):
print "in Parent.method - self.__class__ is ", self.__class__
print "super(Parent, self):", super(Parent, self)
print "super(self.__class__, self):", super(self.__class__, self)
print
class Child(Parent):
def method(self):
print "in Child.method - self.__class__ is ", self.__class__
print "calling super(Child, self).method:"
super(Child, self).method()
print "calling super(self.__class__, self).method"
if type(self) is GrandChild:
print "self.__class__ is GrandChild, so here, "
"super(self.__class__, self).method resolves to
Child.method"
print "enjoy the nice infinite recursion...."
print
super(self.__class__, self).method()
print
class GrandChild(Child):
def method(self):
print "in GrandChild.method - self.__class__ is ", self.__class__
print "calling super(GrandChild, self).method:"
super(GrandChild, self).method()
for obj in (Parent(), Child(), GrandChild()):
obj.method()
print "---n"
Ton éditeur n'est pas capable de faire un simple rechercher/remplacer ?-)
Je comprends, merci à toi et Amaury et vivement Python 3 :)
Après-demain Inch'Allah.
--
Amaury