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.


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ą.


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')

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')

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
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.