This question already has an answer here:
- Why is this an ambiguous MRO? 1 answer
This is the code which I plan to use for my game. But it complains for an MRO error. I don't know why. Can someone explains for me? Many thanks.
class Player:
pass
class Enemy(Player):
pass
class GameObject(Player, Enemy):
pass
g = GameObject()
Your GameObject
is inheriting from Player
and Enemy
. Because Enemy
already inherits from Player
Python now cannot determine what class to look methods up on first; either Player
, or on Enemy
, which would override things defined in Player
.
You don't need to name all base classes of Enemy
here; just inherit from that one class:
class GameObject(Enemy):
pass
Enemy
already includes Player
, you don't need to include it again.
I'll explain the reason the original code doesn't work.
Python needs to decide in which order to search through (direct and indirect) base classes when looking up an instance attribute / method. It does this by linearizing the inheritance graph, that is by converting the graph of base classes into a sequence, using an algorithm called C3 or MRO. The MRO algorithm is the unique algorithm that achieves several desirable properties:
- each ancestor class appears exactly once
- a class always appears before its ancestor ("monotonicity")
- direct parents of the same class should appear in the same order as they are listed in class definition ("consistent local precedence order")
- if children of class
A
always appear before children of classB
, thenA
should appear beforeB
("consistent extended precedence order")
With your code, the second constraint requires that Enemy
appears first; the third constraint requires that Player
appears first. Since there's no way to satisfy all constraints, python reports that your inheritance hierarchy is illegal.
Your code will work if you switch the order of base classes in GameObject
like so:
class GameObject(Enemy, Player):
pass
This is not just a technical detail. In some (hopefully rare) cases, you might want to think about which class should be used to grab the method you called if the method is defined in multiple classes. The order in which you define base classes affects this choice.
What you wrote is you want a GameObject
to be both a Player
and an Enemy
. But an Enemy
is already a Player
. The MRO issue just states that if you had a field a
in Player
, asking for this field in a GameObject
instance would be ambiguous: should it be the a
from the first Player
you inherit or the one from the Player
you inherit through your Enemy
inheritance?
But are you sure you don't want to use composition instead of inheritance, here?
class GameObject(object):
def __init__(self):
self.player = Player()
self.enemy = Enemy()
来源:https://stackoverflow.com/questions/29214888/typeerror-cannot-create-a-consistent-method-resolution-order-mro