Конфликт метакласса, множественное наследование и экземпляр в качестве родителя - PullRequest
4 голосов
/ 20 сентября 2011

Я возился с темными искусствами Python, и есть кое-что, что я хотел бы помочь понять.Учитывая класс Foo, я попытался унаследовать от него несколько способов:

  1. class A(Foo) - Работает, что неудивительно
  2. class B(Foo()) - работает при условии Foo имеетсоответствующий __new__ метод (который я предоставил)
  3. class C(Foo(), Foo) - работает при тех же условиях, что и B
  4. class D(Foo, Foo()) - дает известную ошибку метакласса:

    Traceback (последний вызов был последним):
    Файл "test.py", строка 59, в
    класс D (Foo, Foo ()):
    Ошибка TypeError: конфликт метакласса: метакласс производногокласс должен быть (не строгим) подклассом метаклассов всех его баз

Что именно вызывает этот конфликт?Когда я наследую от (Foo(), Foo) (первый экземпляр, второй класс), это работает, но когда я наследую от (Foo, Foo()) (первый класс, второй экземпляр), это не так.

1 Ответ

5 голосов
/ 20 сентября 2011

Когда вы «присущи экземпляру», то, что вы действительно делаете, это странный способ использования метакласса. Обычно объекты класса являются экземплярами type. В случае вышеупомянутого класса B он наследуется от экземпляра Foo. Это именно то, что произойдет, если вы определили класс с Foo в качестве его метакласса, а затем унаследовали от него.

Итак, мое предположение относительно того, что здесь происходит, заключается в том, что Python обрабатывает базовые классы в обратном порядке MRO.

Класс C работает, потому что первый родительский класс для обработки - Foo, чей класс - type. Это означает, что метакласс D должен быть type или некоторый его подкласс. Затем обрабатывается Foo(), чей класс Foo, который является подклассом type, так что все в порядке.

Класс D терпит неудачу, потому что первый родительский класс, который будет обработан, - Foo(), который устанавливает ограничение, что у D есть метакласс Foo (или подкласс). Затем приходит Foo, чей класс type равен , а не подкласс Foo.

Это полное предположение, но вы можете попытаться выяснить, требует ли документация Python по метаклассам, когда вы умножаете наследование от двух классов с разными метаклассами, где у задействованных метаклассов есть отношение подтипа, что вы размещаете их в определенном порядке. .

...