如何正确使用多个(重新)继承

时间:2014-11-12 15:38:15

标签: python python-2.7 inheritance multiple-inheritance

我遇到以下问题:

  • 有一个基类Unit,它有几个属性,例如: idtypenameskills,...
  • 有不同类型的单元,其中一些具有其他属性,如healthattacktribe,因此自然相关的子类HealthUnit,{{1等等也存在。
  • 有几个单元具有多个这些属性,例如AttackUnitHealthAttackUnit

我想避免这样编码:

HealthAttackTribeUnit

原因很明显。


我尝试使用dict解压缩作为解决方法,有点像这样:

class Unit(object):
    def __init__(self, id, type, name, skills):
        self.id= id
        self.type= type
        self.name= name
        self.skills= skills

class HealthUnit(Unit):
    def __init__(self, id, type, name, skills, health):
        Unit.__init__(self, id, type, name, skills)
        self.health= health

class AttackUnit(Unit):
    def __init__(self, id, type, name, skills, attack):
        Unit.__init__(self, id, type, name, skills)
        self.attack= attack

class HealthAttackUnit(HealthUnit, AttackUnit):
    def __init__(self, id, type, name, skills, health, attack):
        HealthUnit.__init__(self, id, type, name, skills, health)
        AttackUnit.__init__(self, id, type, name, skills, attack)

但即便如此,也会出现大量重复的代码:

class HealthUnit(Unit):
    def __init__(self, health, **args):
        Unit.__init__(self, **args)
        self.health= health

另外,这会多次调用class HealthAttackUnit(HealthUnit, AttackUnit): def __init__(self, health, attack, **args): HealhUnit.__init__(self, health=health, **args) AttackUnit.__init__(self, attack=attack, **args) class HealthAttackTribeUnit(HealthUnit, AttackUnit, TribeUnit): def __init__(self, health, attack, tribe, **args): HealhUnit.__init__(self, health=health, **args) AttackUnit.__init__(self, attack=attack, **args) TribeUnit.__init__(self, tribe=tribe, **args) ,这不太理想。

所以,问题是:是否有更好的,更少的复制/粘贴方式?

更新: dict解压缩很好,但仍然有点烦人,不得不用关键字参数调用所有构造函数。我不喜欢没有Unit.__init__的解决方案,但我估计可能没有{?}}?

1 个答案:

答案 0 :(得分:4)

是的,这正是super函数存在的原因。

确保所有__init__个文件都调用super,Python将为您设计MRO并依次调用相关的类。

class HealthUnit(Unit):
    def __init__(self, **kwargs):
        self.health = kwargs.pop('health')
        super(HealthUnit, self).__init__(**kwargs)

class AttackUnit(Unit):
    def __init__(self, **kwargs):
        self.attack = kwargs.pop('attack')
        super(AttackUnit, self).__init__(**kwargs)

class TribeUnit(Unit):
    def __init__(self, **kwargs):
        self.tribe = kwargs.pop('tribe')
        super(TribeUnit, self).__init__(**kwargs) 

class HealthAttackTribeUnit(HealthUnit, AttackUnit, TribeUnit):
    pass

另请参阅Python核心贡献者(以及偶尔的SO海报)Raymond Hettinger的文章Super considered super,但请注意该帖子中的语法是针对Python 3的,有一个单独的链接指向版本2代码。