Llamar al método de clase de una clase base en Python

105

Considere el siguiente código:

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, como llamo Base.do?

Normalmente usaría supero incluso el nombre de la clase base directamente si este es un método de objeto normal, pero aparentemente no puedo encontrar una manera de llamar al método de clase en la clase base.

En el ejemplo anterior, Base.do(a)imprime Baseclase en lugar de Derivedclase.

Sridhar Ratnakumar
fuente

Respuestas:

121

Si está utilizando una clase de nuevo estilo (es decir, deriva de objecten Python 2, o siempre en Python 3), puede hacerlo super()así:

super(Derived, cls).do(a)

Así es como se invocaría el código en la versión del método de la clase base (es decir print cls, a), desde la clase derivada, con la clsconfiguración de la clase derivada.

David Z
fuente
8
uh uh .. cómo es que nunca se me ocurrió que yo también pudiera usar superen métodos de clase.
Sridhar Ratnakumar
esto solo funciona (debido a una limitación impuesta por super) si la base deriva del objeto, ¿verdad? que haces si ese no es el caso?
ars-longa-vita-brevis
Sí, esto solo funciona para clases de estilo nuevo, que derivan de object. (al menos en Python 2, pero en Py3 creo que todas las clases son de nuevo estilo, IIRC) De lo contrario Base.do(self, ...), creo que tienes que hacerlo , codificando así el nombre de la superclase.
David Z
Por dentro Derived.do(), ¿no es lo clsmismo que Derived?
Ray
@Ray Si en realidad es una instancia Derivedpero no de una subclase, entonces sí.
David Z
15

esto ha pasado un tiempo, pero creo que he encontrado una respuesta. Cuando decoras un método para convertirlo en un método de clase, el método independiente original se almacena en una propiedad llamada '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
fuente
2
Nota: Este enfoque funciona para clases de estilo antiguo donde super () no funciona
Alex Q
2
También disponible como __func__en python 2.7 y 3
dtheodor
-3

Esto funciona para mi:

Base.do('hi')
Ned Batchelder
fuente
9
El clsargumento a continuación, se une a Baseen lugar deDerived
Sridhar Ratnakumar
lo que funciona para mí es esto, que se parece (mucho) a la respuesta de Ned: donde self se deriva de QGraphicsView que tiene paintEvent (QPaintEvent) def paintEvent (self, qpntEvent): print dir (self) QGraphicsView.paintEvent (self, qpntEvent)
user192127