【问题标题】:How to call a parent class's @classmethod from an overridden @classmethod in Python?如何从 Python 中重写的@classmethod 调用父类的@classmethod?
【发布时间】:2013-02-23 20:07:28
【问题描述】:

假设我有一堂课

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。这个可以吗?

注意:示例已简化,因为我的具体示例涉及更多。假设我的目标不是连接字符串。

【问题讨论】:

  • 这是 python 2 还是 3?如果为 2,您是否继承自 object
  • 我对您使用子类作为实例感到困惑。它们根本不是一回事。
  • @Martjin:python 2,继承对象。修复示例。
  • @DanielRoseman 具体的SpaceShuttleGenerator继承自Java中我认为的抽象类AdvancedGenerator,它继承自另一个抽象类SimpleGenerator
  • @KoliberServices:人力资源管理;谨防使用 Java 类比。 Python is not Java,不要陷入试图将 Java 习语引入 Python 的陷阱。

标签: python superclass class-method


【解决方案1】:

使用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)'

【讨论】:

  • 我可以为我的所有派生类创建类方法来打印自己的类名(不是实例的类名)吗?我的意思是A2 = AdvancedGenerator2(AdvancedGenerator) A2.get_description() 并返回:AdvancedGenerator2 AdvancedGenerator SimpleGenerator?
  • @Crusader:你的意思是你想要 MRO 中所有类的名称? return ' '.join([c.__name__ for c in cls.__mro__]).
  • 不,我的意思是如何在类树的某处获取当前类变量。示例类:祖父母->父母->孩子,每个类都有一些类变量'test',我需要得到所有这些变量的连接。用其他语言我可以这样做result = self.var + super().get_var()
  • @Crusader: super().get_var() 不会是类变量。抱歉,您仍然使用过于模糊的术语,无法让我为您提供具体答案。 super() 允许您像访问方法一样访问类属性; super().var 为您提供 MRO 中父类的类变量。如果您需要层次结构中的所有变量,请遍历__mro__ 序列。
  • 如果有参数怎么办?我可以把它写成 def get_description(cls,params): 吗?
猜你喜欢
  • 2021-08-14
  • 2018-09-05
  • 2019-11-08
  • 1970-01-01
  • 2012-12-15
  • 2014-12-01
  • 2021-12-29
  • 2018-04-15
相关资源
最近更新 更多