关于python:typeerror:无法创建一致的方法解析顺序(mro)

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

本问题已经有最佳答案,请猛点这里访问。

这是我计划在游戏中使用的代码。但它抱怨MRO错误。我不知道为什么。有人能给我解释一下吗?多谢。

1
2
3
4
5
6
7
8
9
10
class Player:
    pass

class Enemy(Player):
    pass

class GameObject(Player, Enemy):
    pass

g = GameObject()

你的GameObject是从PlayerEnemy继承来的。因为Enemy已经从Playerpython继承了,所以现在无法确定首先要查找哪些类的方法;PlayerEnemy上的方法将覆盖Player中定义的内容。

您不需要在这里命名Enemy的所有基类;只需从该类继承:

1
2
class GameObject(Enemy):
    pass

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


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

在查找实例属性/方法时,python需要决定按哪个顺序搜索(直接和间接)基类。它通过线性化继承图来实现这一点,也就是通过使用一种叫做c3或mro的算法将基类图转换成序列。MRO算法是一种独特的算法,可实现以下几个理想特性:

  • 每个祖先类只出现一次
  • 类总是出现在其祖先之前("单调性")。
  • 同一类的直接父类应按照类定义中列出的顺序显示("一致的本地优先顺序")。
  • 如果a类的子类总是出现在B类的子类之前,那么a类应该出现在B类之前("一致的扩展优先顺序")。
  • 对于代码,第二个约束要求Enemy首先出现;第三个约束要求Player首先出现。由于无法满足所有约束,Python报告您的继承层次结构是非法的。

    如果您像这样切换EDOCX1[0]中的基类顺序,您的代码将工作:

    1
    2
    class GameObject(Enemy, Player):
        pass

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


    你写的是你想要一个GameObject同时是一个Player和一个Enemy。但是一个Enemy已经是一个Player。MRO的问题只是说,如果你在Player中有一个字段a,在GameObject实例中要求这个字段将是含糊不清的:它应该是你从第一个Player继承的a,还是你通过Enemy继承的Player继承的?

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

    1
    2
    3
    4
    class GameObject(object):
        def __init__(self):
            self.player = Player()
            self.enemy = Enemy()