Виклик методу базового класу в Python


105

Розглянемо наступний код:

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

Звідки Derived.do, як мені дзвонити Base.do?

Я зазвичай використовую superабо навіть ім'я базового класу безпосередньо, якщо це звичайний об'єктний метод, але, мабуть, я не можу знайти спосіб викликати classmethod в базовому класі.

У наведеному вище прикладі Base.do(a)друкується Baseклас замість Derivedкласу.


Відповіді:


121

Якщо ви використовуєте клас нового стилю (тобто походить від objectPython 2 або завжди в Python 3), ви можете це зробити super()так:

super(Derived, cls).do(a)

Ось як можна було б викликати код у версії методу базового класу (тобто print cls, a) з похідного класу з clsвстановленням на похідний клас.


8
е-е-е ... як же мені ніколи не траплялося, що я також можу використовувати і superна classmethods.
Шрідхар Ратнакумар

це працює лише (через обмеження, накладене супер), якщо база походить від об'єкта, правда? що ви робите, якщо це не так?
ars-longa-vita-brevis

Так, це працює лише для класів нового стилю, які походять від object. (принаймні, в Python 2, але в Py3, я думаю, що всі класи є новим стилем, IIRC) Інакше вам потрібно зробити Base.do(self, ...), я думаю, тим самим важко кодуючи назву суперкласу.
David Z

Всередині Derived.do(), не clsте саме, що Derived?
Рей

@Ray Якщо це насправді екземпляр, Derivedале не підклас, то так.
David Z

15

це минуло певний час, але я думаю, що я, можливо, знайшов відповідь. Коли ви прикрашаєте метод стати методом classs, оригінальний незв'язаний метод зберігається у властивості під назвою '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
Примітка. Цей підхід працює для класів старого стилю, де super () не працює
Alex Q

2
Також доступний як __func__у python 2.7 та 3
dtheodor

-3

Це працює для мене:

Base.do('hi')

9
clsАргумент потім буде зобов'язаний BaseзамістьDerived
Шрідхара Ratnakumar

що для мене працює, це те, що виглядає (дуже багато) як відповідь Неда: де власне похідне від QGraphicsView, який має paintEvent (QPaintEvent) def paintEvent (self, qpntEvent): print dir (self) QGraphicsView.paintEvent (self, qpntEvent)
user192127
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.