TypeError: Cannot create a consistent method resolution order (MRO)

TypeError: Cannot create a consistent method resolution order (MRO)

这是我打算用于我的游戏的代码,但它抱怨 MRO 错误:

class Player:
    pass

class Enemy(Player):
    pass

class GameObject(Player, Enemy):
    pass

g = GameObject()

您的 GameObject 继承自 Player Enemy。因为 Enemy 已经 继承自 Player Python 现在无法确定 class 首先查找方法; PlayerEnemy,这将覆盖 Player.

中定义的内容

您不需要在这里命名 Enemy 的所有基 class;只是继承那个 class:

class GameObject(Enemy):
    pass

Enemy已经包含了Player,你不需要再包含了。

您写的是您希望 GameObject 既是 Player 又是 Enemy。但是 Enemy 已经是 Player。 MRO 问题只是指出,如果您在 Player 中有一个字段 a,那么在 GameObject 实例中请求该字段将是不明确的:它应该是 a 来自第一个 Player 是您继承的还是 Player 您通过 Enemy 继承的?

但是你确定不想在这里使用组合而不是继承吗?

class GameObject(object):
    def __init__(self):
        self.player = Player()
        self.enemy = Enemy()

我会解释原始代码不起作用的原因。

Python 需要决定在查找实例属性/方法时搜索(直接和间接)基础 classes 的顺序。它通过线性化继承图来实现这一点,即将基数 classes 的图转换为序列,使用称为 C3 or MRO 的算法。 MRO 算法是实现几个理想属性的独特算法:

  1. 每个祖先class只出现一次
  2. a class 总是出现在其祖先 ("monotonicity")
  3. 之前 相同 class 的
  4. 直接 parents 应该按照它们在 class 定义 ("consistent local precedence order")
  5. 中列出的相同顺序出现
  6. 如果 children of class A 总是出现在 children of class B 之前,那么 A 应该出现在 B ("consistent extended precedence order")
  7. 之前

对于您的代码,第二个约束条件要求 Enemy 首先出现;第三个约束要求 Player 首先出现。由于无法满足所有约束,python 报告您的继承层次结构不合法。

如果您像这样在 GameObject 中切换基数 classes 的顺序,您的代码将起作用:

class GameObject(Enemy, Player):
    pass

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