python inheritance typeerror method-resolution-order

python - TypeError: no se puede crear un orden de resolución de método(MRO) coherente



inheritance method-resolution-order (3)

Este es el código que planeo usar para mi juego. Pero se queja por un error MRO. No se porque. ¿Alguien puede explicar por mí? Muchas gracias.

class Player: pass class Enemy(Player): pass class GameObject(Player, Enemy): pass g = GameObject()


Explicaré la razón por la cual el código original no funciona.

Python necesita decidir en qué orden buscar a través de las clases base (directas e indirectas) al buscar un atributo / método de instancia. Para ello, linealiza el gráfico de herencia, es decir, convierte el gráfico de clases base en una secuencia, utilizando un algoritmo llamado C3 o MRO . El algoritmo MRO es el algoritmo único que logra varias propiedades deseables:

  1. cada clase de antepasado aparece exactamente una vez
  2. una clase siempre aparece antes de su antepasado ("monotonicidad")
  3. los padres directos de la misma clase deben aparecer en el mismo orden en que aparecen en la definición de clase ("orden de precedencia local coherente")
  4. si los hijos de la clase A siempre aparecen antes que los hijos de la clase B , entonces A debería aparecer antes que B ("orden de precedencia extendida consistente")

Con su código, la segunda restricción requiere que el Enemy aparezca primero; La tercera restricción requiere que el Player aparezca primero. Como no hay forma de satisfacer todas las restricciones, python informa que su jerarquía de herencia es ilegal.

Su código funcionará si cambia el orden de las clases base en GameObject así:

class GameObject(Enemy, Player): pass

Esto no es solo un detalle técnico. En algunos casos (con suerte raros), es posible que desee pensar en qué clase se debe utilizar para obtener el método que llamó si el método se define en varias clases. El orden en el que define las clases base afecta esta elección.


Lo que escribiste es que quieres que un GameObject sea ​​un Player y un Enemy . Pero un Enemy ya es un Player . El problema de MRO solo indica que si tuvieras un campo a en Player , pedir este campo en una instancia de GameObject sería ambiguo: si se trata del a del primer Player que heredas o el del Player que heredas a través de tu herencia Enemy ?

Pero, ¿estás seguro de que no quieres usar composición en lugar de herencia, aquí?

class GameObject(object): def __init__(self): self.player = Player() self.enemy = Enemy()


Su GameObject está heredando de Player y Enemy . Debido a que Enemy ya hereda de Player Python, ahora no puede determinar en qué clase buscar primero los métodos; ya sea Player o en Enemy , lo que anularía las cosas definidas en Player .

No necesita nombrar todas las clases base de Enemy aquí; simplemente hereda de esa clase:

class GameObject(Enemy): pass

Enemy ya incluye Player , no necesitas volver a incluirlo.