Chamando o método de classe de uma classe base em Python


105

Considere o seguinte 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 faço para ligar Base.do?

Eu normalmente usaria superou mesmo o nome da classe base diretamente se este for um método de objeto normal, mas aparentemente não consigo encontrar uma maneira de chamar o método de classe na classe base.

No exemplo acima, Base.do(a)imprime Baseclasse em vez de Derivedclasse.


Respostas:


121

Se você estiver usando uma classe de novo estilo (ou seja, deriva do objectPython 2 ou sempre do Python 3), você pode fazer isso da super()seguinte maneira:

super(Derived, cls).do(a)

É assim que você chamaria o código na versão do método da classe base (ou seja print cls, a), da classe derivada, clssendo definido como a classe derivada.


8
uh uh .. como é que nunca me ocorreu que eu também pudesse usar os supermétodos de classe.
Sridhar Ratnakumar

isso só funciona (devido a uma limitação imposta por super) se a base deriva de objeto, certo? o que você faz se não for o caso?
ars-longa-vita-brevis

Sim, isso só funciona para classes de novo estilo, que derivam de object. (pelo menos em Python 2, mas em Py3 eu acho que todas as classes são de novo estilo, IIRC) Caso contrário, você terá que fazer Base.do(self, ...), eu acho, assim codificando permanentemente o nome da superclasse.
David Z de

Por dentro Derived.do(), não é clso mesmo que Derived?
Ray,

@Ray Se for realmente uma instância de, Derivedmas não de uma subclasse, então sim.
David Z,

15

já faz um tempo, mas acho que posso ter encontrado uma resposta. Quando você decora um método para se tornar um método de classe, o método original não associado é armazenado em uma propriedade chamada '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')

2
Observação: essa abordagem funciona para classes de estilo antigo em que super () não funciona
Alex Q

2
Também disponível como __func__em python 2.7 e 3
dtheodor

-3

Isso funciona para mim:

Base.do('hi')

9
O clsargumento será então obrigado a Basevez deDerived
Sridhar Ratnakumar

o que funciona para mim é isto - que se parece (muito) com a resposta de Ned: onde self deriva de QGraphicsView que tem paintEvent (QPaintEvent) def paintEvent (self, qpntEvent): print dir (self) QGraphicsView.paintEvent (self, qpntEvent)
usuário192127
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.