简体   繁体   中英

Calling a base class's classmethod in Python

Consider the following code:

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

From Derived.do , how do I call Base.do ?

I would normally use super or even the base class name directly if this is a normal object method, but apparently I can't find a way to call the classmethod in the base class.

In the above example, Base.do(a) prints Base class instead of Derived class.

If you're using a new-style class (ie derives from object in Python 2, or always in Python 3), you can do it with super() like this:

super(Derived, cls).do(a)

This is how you would invoke the code in the base class's version of the method (ie print cls, a ), from the derived class, with cls being set to the derived class.

this has been a while, but I think I may have found an answer. When you decorate a method to become a classmethod the original unbound method is stored in a property named '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')

Building on the answer from @David Z using:

super(Derived, cls).do(a)

Which can be further simplified to:

super(cls, cls).do(a)

I often use classmethods to provide alternative ways to construct my objects. In the example below I use the super functions as above for the class method load that alters the way that the objects are created:

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)

Output:

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

这对我有用:

Base.do('hi')

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM