在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如果这是一个普通的对象方法,通常我会直接使用甚至直接使用基类名称,但是显然我找不到在基类中调用类方法的方法。

在上面的示例中,Base.do(a)打印Baseclass而不是Derivedclass。


Answers:


121

如果您使用的是新样式的类(例如,是从objectPython 2 派生的,或者总是在Python 3中派生的),则可以这样操作super()

super(Derived, cls).do(a)

这是您如何在基类版本的方法(即print cls, a)中从派生类调用代码并将cls其设置为派生类的方式。


8
嗯..我怎么也没想到我也可以super在类方法上使用它。
Sridhar Ratnakumar,2009年

仅当基数源自对象时,这才起作用(由于super的限制),对吧?如果不是这种情况该怎么办?
ars-longa-vita-brevis 2014年

是的,这仅适用于派生自的新型类object。(至少在Python 2中,但在Py3中,我认为所有类都是新样式,即IIRC),否则Base.do(self, ...),我认为您必须这样做,从而硬编码超类的名称。
David Z

里面Derived.do()cls一样Derived吗?

@Ray如果它实际上Derived是子类的实例,但不是子类的实例,则为是。
David Z

15

这已经有一段时间了,但是我想我可能已经找到了答案。当您装饰一个方法成为类方法时,原始的未绑定方法存储在名为“ 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 2014年

-3

这对我有用:

Base.do('hi')

9
cls参数将被绑定到Base替代Derived
斯瑞达Ratnakumar

对我有用的是-看起来(与Ned的回答非常相似):自我是从QGraphicsView派生而来的,它具有paintEvent(QPaintEvent)def paintEvent(自我,qpntEvent):print dir(自我)QGraphicsView.paintEvent(自我,qpntEvent)
user192127 2012年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.