如何从重写的@classmethod调用父类的@classmethod?

17 投票
1 回答
7977 浏览
提问于 2025-04-17 18:23

假设我有一个类

class SimpleGenerator(object):
    @classmethod
    def get_description(cls):
        return cls.name

class AdvancedGenerator(SimpleGenerator):
    @classmethod
    def get_description(cls):
        desc = SimpleGenerator.get_description() # this fails
        return desc + ' Advanced(tm) ' + cls.adv_feature

现在我把上面每个类都扩展了一下,变成了每个类都有具体实现的样子:

class StringGenerator(SimpleGenerator)
    name = 'Generates strings'
    def do_something():
        pass

class SpaceShuttleGenerator(AdvancedGenerator)
    name = 'Generates space shuttles'
    adv_feature = ' - builds complicated components'
    def do_something():
        pass

现在假设我调用了

SpaceShuttleGenerator.get_description()

问题是,在 AdvancedGenerator 里,我想调用 SimpleGenerator 里的一个方法,并且传入一个类的实例,具体来说是 SpaceShuttleGenerator。这样做可以吗?

注意:这个例子是简化过的,因为我的实际例子要复杂得多。假设我的目标不是简单地拼接字符串。

1 个回答

17

使用 super()

@classmethod
def get_description(cls):
    desc = super(AdvancedGenerator, cls).get_description()
    return desc + ' Advanced(tm) ' + cls.adv_feature

使用 SimpleGenerator.get_description()super(AdvancedGenerator, cls).get_description() 的区别在于 cls 的值会不同。当你直接调用类的时候,cls 会被设置为 SimpleGenerator;而使用 super() 的时候,cls 会指向 AdvancedGenerator

比较一下你的代码(调整后使用 __name__ 来说明这个区别):

>>> class SimpleGenerator(object):
...     @classmethod
...     def get_description(cls):
...         return cls.__name__
... 
>>> class AdvancedGenerator(SimpleGenerator):
...     @classmethod
...     def get_description(cls):
...         desc = SimpleGenerator.get_description() 
...         return desc + ' Advanced(tm)'
... 
>>> AdvancedGenerator.get_description()
'SimpleGenerator Advanced(tm)'

以及使用 super() 的情况:

>>> class AdvancedGenerator(SimpleGenerator):
...     @classmethod
...     def get_description(cls):
...         desc = super(AdvancedGenerator, cls).get_description()
...         return desc + ' Advanced(tm)'
... 
>>> AdvancedGenerator.get_description()
'AdvancedGenerator Advanced(tm)'

撰写回答