TypeError: unable to create consistent method resolution order (MRO)

This is the code that I plan to use for my game. But he complains about the error of the MRO. I do not know why. Can someone explain to me? Thank you very much.

class Player: pass class Enemy(Player): pass class GameObject(Player, Enemy): pass g = GameObject() 
+21
python inheritance typeerror method-resolution-order
Mar 23 '15 at 16:04
source share
3 answers

Your GameObject inherits from Player and Enemy . Since Enemy already inheriting from Player , Python can no longer determine which class will first search for methods; either Player , or Enemy , which will override everything that is defined in Player .

Here you do not need to specify all the Enemy base classes; just inherit from this one class:

 class GameObject(Enemy): pass 

Enemy already includes Player , you do not need to enable it again.

+47
Mar 23 '15 at 16:06
source share

I will explain the reason why the source code does not work.

Python must decide in which order to look for (direct and indirect) base classes when searching for an attribute / instance method. He does this by linearizing the inheritance graph, that is, by converting the base class graph into a sequence using an algorithm called C3 or MRO . The MRO algorithm is a unique algorithm that provides several desired properties:

  • each class of ancestors appears exactly once
  • a class always appears before its ancestor ("monotony")
  • direct parents of the same class should be displayed in the same order as they are specified in the class definition ("consistent local priority order")
  • if class A children always appear in front of children of class B , then A should appear before B ("consistent extended priority order")

With your code, the second limitation requires Enemy appear first; the third limitation requires Player appear first. Since there is no way to satisfy all restrictions, python reports that your inheritance hierarchy is illegal.

Your code will work if you switch the order of the base classes in GameObject as follows:

 class GameObject(Enemy, Player): pass 

This is not just a technical detail. In some (hopefully rare) cases, you may need to think about which class should be used to capture the method that you called if the method is defined in several classes. The order in which you define the base classes affects this choice.

+8
02 mar. '17 at 22:57
source share

What you wrote is that you want GameObject be both Player and Enemy . But Enemy already has a Player . The MRO problem is that if you had a field in Player , the query for that field in the GameObject instance would be ambiguous: should it be a from the first Player that you inherit, or one of the Player that you inherit through Enemy inheritance?

But are you sure you don't want to use composition instead of inheritance?

 class GameObject(object): def __init__(self): self.player = Player() self.enemy = Enemy() 
+4
Mar 23 '15 at 16:10
source share



All Articles