在Python中调用基类的类方法

131 投票
4 回答
58162 浏览
提问于 2025-04-15 13:33

考虑以下代码:

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) 打印的是 Base 类,而不是 Derived 类。

4 个回答

3

在@David Z的回答基础上,使用了:

super(Derived, cls).do(a)

这个可以进一步简化为:

super(cls, cls).do(a)

我经常使用类方法来提供不同的方式来创建我的对象。在下面的例子中,我使用了上面提到的super函数,来改变对象的创建方式,具体是在类方法load中:

class Base():
    
    def __init__(self,a):
        self.a = a
    
    @classmethod
    def load(cls,a):
        return cls(a=a)
    
class SubBase(Base): 

    @classmethod
    def load(cls,b):
        a = b-1
        return super(cls,cls).load(a=a)
    
base = Base.load(a=1)
print(base)
print(base.a)

sub = SubBase.load(b=3)
print(sub)
print(sub.a)

输出结果:

<__main__.Base object at 0x128E48B0>
1
<__main__.SubBase object at 0x128E4710>
2
17

这已经有一段时间了,但我想我可能找到了答案。当你把一个方法装饰成类方法时,原来的未绑定方法会被存储在一个叫做'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')
146

如果你在使用一种新式的类(也就是说,在Python 2中是从object派生的,或者在Python 3中总是这样),你可以用super()来做到这一点,像这样:

super(Derived, cls).do(a)

这就是你如何从派生类调用基类中方法的代码(也就是print cls, a),其中cls会被设置为派生类。

撰写回答