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 首先查找方法; Player
或 Enemy
,这将覆盖 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 算法是实现几个理想属性的独特算法:
- 每个祖先class只出现一次
- a class 总是出现在其祖先 ("monotonicity")
之前
相同 class 的 - 直接 parents 应该按照它们在 class 定义 ("consistent local precedence order")
中列出的相同顺序出现
- 如果 children of class
A
总是出现在 children of class B
之前,那么 A
应该出现在 B
("consistent extended precedence order") 之前
对于您的代码,第二个约束条件要求 Enemy
首先出现;第三个约束要求 Player
首先出现。由于无法满足所有约束,python 报告您的继承层次结构不合法。
如果您像这样在 GameObject
中切换基数 classes 的顺序,您的代码将起作用:
class GameObject(Enemy, Player):
pass
这不仅仅是一个技术细节。在某些(希望很少见的)情况下,您可能想考虑如果方法定义在多个 class 中,应该使用哪个 class 来获取您调用的方法。您定义基数 classes 的顺序会影响此选择。
这是我打算用于我的游戏的代码,但它抱怨 MRO 错误:
class Player:
pass
class Enemy(Player):
pass
class GameObject(Player, Enemy):
pass
g = GameObject()
您的 GameObject
继承自 Player
和 Enemy
。因为 Enemy
已经 继承自 Player
Python 现在无法确定 class 首先查找方法; Player
或 Enemy
,这将覆盖 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 算法是实现几个理想属性的独特算法:
- 每个祖先class只出现一次
- a class 总是出现在其祖先 ("monotonicity") 之前 相同 class 的
- 直接 parents 应该按照它们在 class 定义 ("consistent local precedence order") 中列出的相同顺序出现
- 如果 children of class
A
总是出现在 children of classB
之前,那么A
应该出现在B
("consistent extended precedence order") 之前
对于您的代码,第二个约束条件要求 Enemy
首先出现;第三个约束要求 Player
首先出现。由于无法满足所有约束,python 报告您的继承层次结构不合法。
如果您像这样在 GameObject
中切换基数 classes 的顺序,您的代码将起作用:
class GameObject(Enemy, Player):
pass
这不仅仅是一个技术细节。在某些(希望很少见的)情况下,您可能想考虑如果方法定义在多个 class 中,应该使用哪个 class 来获取您调用的方法。您定义基数 classes 的顺序会影响此选择。