Я объясню причину, по которой исходный код не работает.
Python должен решить, в каком порядке искать базовые классы (прямые и косвенные) при поиске атрибута/метода экземпляра. Он делает это путем линеаризации графа наследования, то есть путем преобразования графика базовых классов в последовательность, используя алгоритм, называемый C3 or MRO. Алгоритм MRO является уникальный алгоритм, который достигает нескольких желательных свойств:
- каждый класс предок появляется ровно один раз
- класс всегда появляется перед его предка («монотонности»)
- прямые родители одного и того же класса должны появляюсь в том же порядке, в котором они перечислены в определении класса («соответствуют локальному порядку старшинства»)
- если дети класса
A
всегда появляются перед детьми класса B
, то A
должны предстать перед B
(«последовательным расширенным порядком старшинства»)
С кодом, для второго ограничения требуется, чтобы сначала появилось Enemy
; третье ограничение требует, чтобы сначала появилось Player
. Поскольку нет возможности удовлетворить все ограничения, отчеты python о том, что ваша иерархия наследования является незаконной.
Ваш код будет работать, если вы изменить порядок базовых классов в GameObject
так:
class GameObject(Enemy, Player):
pass
Это не просто техническая деталь. В некоторых (надеюсь, редких) случаях вам может понадобиться подумать о том, какой класс следует использовать для захвата метода, который вы вызывали, если метод определен в нескольких классах. На этот выбор влияет порядок, в котором вы определяете базовые классы.
Это гораздо лучший ответ, чем принятый. –