Wywołanie metody klasy bazowej w Pythonie

105

Rozważ następujący kod:

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

Od Derived.do, jak mam zadzwonić Base.do?

Normalnie użyłbym superlub nawet bezpośrednio nazwy klasy bazowej, jeśli jest to normalna metoda obiektu, ale najwyraźniej nie mogę znaleźć sposobu na wywołanie metody class w klasie bazowej.

W powyższym przykładzie, Base.do(a)drukuje Baseklasy zamiast Derivedklasy.

Sridhar Ratnakumar
źródło

Odpowiedzi:

121

Jeśli używasz klasy nowego stylu (tzn. Pochodzi z objectPythona 2 lub zawsze z Pythona 3), możesz to zrobić w super()następujący sposób:

super(Derived, cls).do(a)

W ten sposób można wywołać kod w wersji metody klasy bazowej (tj. print cls, a) Z klasy pochodnej, clsustawiając go na klasę pochodną.

David Z
źródło
8
uh ... jak to się stało, że nigdy nie przyszło mi do głowy, że mogę używać supermetod klasowych.
Sridhar Ratnakumar
to działa tylko (z powodu ograniczenia nałożonego przez super), jeśli podstawa pochodzi z obiektu, prawda? co robisz, jeśli tak nie jest?
ars-longa-vita-brevis
Tak, działa to tylko w przypadku klas w nowym stylu, które pochodzą z object. (przynajmniej w Pythonie 2, ale w Py3 myślę, że wszystkie klasy są w nowym stylu, IIRC) W przeciwnym razie Base.do(self, ...), myślę, że musisz to zrobić , tym samym zakodując na stałe nazwę nadklasy.
David Z
Wewnątrz Derived.do(), to nie clsto samo co Derived?
Ray
@Ray Jeśli jest to rzeczywiście instancja Derivedpodklasy, ale nie jej, to tak.
David Z
15

to było jakiś czas, ale myślę, że mogłem znaleźć odpowiedź. Kiedy dekorujesz metodę, aby stała się metodą klasową, oryginalna niezwiązana metoda jest przechowywana we właściwości o nazwie „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
źródło
2
Uwaga: To podejście działa w przypadku klas starego stylu, w których super () nie działa
Alex Q,
2
Dostępne również jako __func__python 2.7 i 3
dtheodor
-3

To działa dla mnie:

Base.do('hi')
Ned Batchelder
źródło
9
clsArgumentem zostanie związany BasezamiastDerived
Szridhar Ratnakumar
dla mnie działa to - co wygląda (bardzo) jak odpowiedź Neda: gdzie self pochodzi z QGraphicsView, który ma paintEvent (QPaintEvent) def paintEvent (self, qpntEvent): print dir (self) QGraphicsView.paintEvent (self, qpntEvent)
user192127