TypeError:无法创建一致的方法解析顺序(MRO)

84 python inheritance typeerror method-resolution-order

这是我计划用于游戏的代码.但它抱怨MRO错误.我不知道为什么.有人能为我解释一下吗?非常感谢.

class Player:
    pass

class Enemy(Player):
    pass

class GameObject(Player, Enemy):
    pass

g = GameObject()
Run Code Online (Sandbox Code Playgroud)

Mar*_*ers 109

GameObject是继承Player Enemy.因为Enemy 已经PlayerPython 继承现在无法确定首先查找方法的类; 或者Player,或者Enemy,它将覆盖在中定义的东西Player.

您不需要在此命名所有基类Enemy; 只从这一个类继承:

class GameObject(Enemy):
    pass
Run Code Online (Sandbox Code Playgroud)

Enemy已包含Player,您不需要再次包含它.


max*_*max 64

我将解释原始代码不起作用的原因.

在查找实例属性/方法时,Python需要决定搜索(直接和间接)基类的顺序.它通过线性化继承图来实现这一点,即通过使用名为C3或MRO的算法将基类图转换为序列.MRO算法是一种独特的算法,可实现多种理想的属性:

  1. 每个祖先类只出现一次
  2. 一个类总是出现在它的祖先之前("单调性")
  3. 同一类的直接父类应按其在类定义中列出的顺序出现("一致的本地优先顺序")
  4. 如果班级的孩子A总是出现在班级的孩子面前B,那么A应该出现在之前B("一致的扩展优先顺序")

使用您的代码,第二个约束要求Enemy首先出现; 第三个约束要求Player首先出现.由于没有办法满足所有约束,python报告你的继承层次结构是非法的.

如果你GameObject像这样切换基类的顺序,你的代码将会起作用:

class GameObject(Enemy, Player):
    pass
Run Code Online (Sandbox Code Playgroud)

这不仅仅是技术细节.在某些(希望很少见)的情况下,如果在多个类中定义方法,您可能需要考虑应该使用哪个类来获取您调用的方法.定义基类的顺序会影响此选择.

  • 这是一个比接受的答案要好得多的答案. (13认同)

Fra*_*las 6

你写的是你想成为GameObject一个Player和一个Enemy.但是Enemy已经是一个了Player.该MRO问题只是指出,如果你有一个领域aPlayer,在询问这个领域GameObject实例将是不明确的:它应该是a从第一个Player你继承,或从一个Player你通过继承Enemy遗产?

但是你确定你不想使用合成而不是继承吗?

class GameObject(object):
    def __init__(self):
        self.player = Player()
        self.enemy = Enemy()
Run Code Online (Sandbox Code Playgroud)