Appel de la méthode de classe d'une classe de base en Python

105

Considérez le code suivant:

class Base(object):

    @classmethod
    def do(cls, a):
        print cls, a

class Derived(Base):

    @classmethod
    def do(cls, a):
        print 'In derived!'
        # Base.do(cls, a) -- can't pass `cls`
        Base.do(a)

if __name__ == '__main__':
    d = Derived()
    d.do('hello')

> $ python play.py  
> In derived! 
> <class '__main__.Base'> msg

De Derived.do, comment appeler Base.do?

J'utiliserais normalement superou même le nom de la classe de base directement s'il s'agit d'une méthode d'objet normale, mais apparemment, je ne peux pas trouver un moyen d'appeler la méthode de classe dans la classe de base.

Dans l'exemple ci-dessus, Base.do(a)imprime la Baseclasse au lieu de la Derivedclasse.

Sridhar Ratnakumar
la source

Réponses:

121

Si vous utilisez une classe de nouveau style (c'est-à-dire dérivée de objectPython 2, ou toujours de Python 3), vous pouvez le faire super()comme ceci:

super(Derived, cls).do(a)

C'est ainsi que vous invoqueriez le code dans la version de la classe de base de la méthode (c'est-à-dire print cls, a), à partir de la classe dérivée, en clsétant défini sur la classe dérivée.

David Z
la source
8
euh euh .. comment se fait il ne m'est jamais venu superà l'esprit que je puisse aussi utiliser des méthodes de classe.
Sridhar Ratnakumar
cela ne fonctionne (en raison d'une limitation imposée par super) que si la base dérive de l'objet, non? que faites-vous si ce n'est pas le cas?
ars-longa-vita-brevis
Ouais, cela ne fonctionne que pour les classes de style nouveau, qui dérivent de object. (au moins en Python 2, mais en Py3, je pense que toutes les classes sont de nouveau style, IIRC) Sinon, vous devez le faire Base.do(self, ...), je pense, codant ainsi en dur le nom de la superclasse.
David Z du
À l'intérieur Derived.do(), n'est-ce pas clsla même chose Derived?
Ray
@Ray S'il s'agit en fait d'une instance Derivedmais pas d'une sous-classe, alors oui.
David Z
15

cela fait un moment, mais je pense avoir trouvé une réponse. Lorsque vous décorez une méthode pour qu'elle devienne une méthode de classe, la méthode indépendante d'origine est stockée dans une propriété nommée 'im_func':

class Base(object):
    @classmethod
    def do(cls, a):
        print cls, a

class Derived(Base):

    @classmethod
    def do(cls, a):
        print 'In derived!'
        # Base.do(cls, a) -- can't pass `cls`
        Base.do.im_func(cls, a)

if __name__ == '__main__':
    d = Derived()
    d.do('hello')
Nikolas
la source
2
Remarque: Cette approche fonctionne pour les classes de style ancien où super () ne fonctionne pas
Alex Q
2
Aussi disponible __func__en python 2.7 et 3
dtheodor
-3

Cela fonctionne pour moi:

Base.do('hi')
Ned Batchelder
la source
9
L' clsargument sera alors lié à la Baseplace deDerived
Sridhar Ratnakumar
ce qui fonctionne pour moi est ceci - qui ressemble (beaucoup) à la réponse de Ned: où self dérive de QGraphicsView qui a paintEvent (QPaintEvent) def paintEvent (self, qpntEvent): print dir (self) QGraphicsView.paintEvent (self, qpntEvent)
user192127