This is the code which I plan to use for my game, but it complains about an MRO error:
class Player: pass class Enemy(Player): pass class GameObject(Player, Enemy): pass g = GameObject()
GameObject is inheriting from
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
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.
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
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
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()
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:
Aalways appear before children of class
Ashould appear before
B(“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.