Parfois, les textes doivent être lus davantage pour le sens de l'idée que pour les détails. C'est l'un de ces cas.
Sur la page liée, les exemples 2.5, 2.6 et 2.7 devraient tous utiliser une méthode, do_your_stuff
. (C'est-à-dire que do_something
devrait être changé en do_your_stuff
.)
De plus, comme l'a souligné Ned Deily, A.do_your_stuff
doit être une méthode de classe.
class A(object):
@classmethod
def do_your_stuff(cls):
print 'This is A'
class B(A):
@classmethod
def do_your_stuff(cls):
super(B, cls).do_your_stuff()
B.do_your_stuff()
super(B, cls).do_your_stuff
retourne une méthode liée (voir note de bas de page 2). Comme cls
a été passé en second argument à super()
, c'est cls
qui est lié à la méthode retournée. En d'autres termes, c'est cls
qui est passé en premier argument à la méthode do_your_stuff()
de la classe A.
Pour répéter : super(B, cls).do_your_stuff()
fait que la méthode do_your_stuff
de A
est appelée avec cls
passé en premier argument. Pour que cela fonctionne, la méthode do_your_stuff
de A
doit être une méthode de classe. La page liée ne mentionne pas cela, mais c'est définitivement le cas.
PS. do_something = classmethod(do_something)
est l'ancienne méthode de faire une méthode de classe. La méthode plus récente est d'utiliser le décorateur @classmethod.
Il est important de noter que super(B, cls)
ne peut pas être remplacé par super(cls, cls)
. Le faire pourrait entraîner des boucles infinies. Par exemple,
class A(object):
@classmethod
def do_your_stuff(cls):
print('This is A')
class B(A):
@classmethod
def do_your_stuff(cls):
print('This is B')
# super(B, cls).do_your_stuff() # CORRECT
super(cls, cls).do_your_stuff() # WRONG
class C(B):
@classmethod
def do_your_stuff(cls):
print('This is C')
# super(C, cls).do_your_stuff() # CORRECT
super(cls, cls).do_your_stuff() # WRONG
C.do_your_stuff()
va déclencher une RuntimeError: maximum recursion depth exceeded while calling a Python object
.
Si cls
est C
, alors super(cls, cls)
va chercher dans C.mro()
la classe qui suit C
.
In [161]: C.mro()
Out[161]: [__main__.C, __main__.B, __main__.A, object]
Comme cette classe est B
, lorsque cls
est C
, super(cls, cls).do_your_stuff()
appelle toujours B.do_your_stuff
. Puisque super(cls, cls).do_your_stuff()
est appelée à l'intérieur de B.do_your_stuff
, cela finit par appeler B.do_your_stuff
en boucle infinie.
En Python3, la forme à 0 arguments de super
a été ajoutée afin que super(B, cls)
puisse être remplacé par super()
, et Python3 déduira du contexte que super()
dans la définition de class B
doit être équivalent à super(B, cls)
.
Mais en aucun cas super(cls, cls)
(ou pour des raisons similaires, super(type(self), self)
) n'est correct.