Проблема в том, что Bar.VALUE.__init__
вызывается до того, как Bar
существует.
Вы можете видеть, где это происходит в EnumMeta.__new__
, но даже не глядя на код, имеет для работы таким образом: весь смысл Enum
класса заключается в том, что его элементы перечисления являются постоянными значениями, которые действуют как атрибуты класса, а также являются его экземплярами.
При этом этот код будет выдавать точно такую же ошибку в 3.4+ с модулем stdlib enum
и аналогичные ошибки при множественных заменах enum
сторонних производителей.
В общем случае, если у вас есть Enumв иерархиях вообще, вы должны помещать значения только в «листовые» классы и поведение только в неконечные классы.Однако единственное ограничение, которое фактически задокументировано в Ограниченное наследование перечислений , - это отсутствие значений в неконечных классах, поэтому технически то, что вы пытаетесь сделать, должно быть законным, даже если это необычно и никогда не было явнопредназначен для работы.
Если вы использовали Python 3, есть довольно простой обходной путь: просто используйте super()
вместо super(Bar, self)
, и это не имеет значения, чем Bar
несуществует еще.
В Python 2, поскольку это невозможно, вам нужно вручную смоделировать super
.Для полной общности это означает написание кода для обхода mro
и т. Д., Но поскольку множественное наследование, включая два или более классов Enum
, в любом случае не будет работать, вам будет достаточно просто статически его жестко кодировать:
def __init__(self, value):
Foo.__init__(self)
В качестве альтернативы, если вы измените свой дизайн, чтобы поместить все поведение в неконечные классы, это также будет работать:
class Foo(Enum):
def __init__(self):
pass
class Bar(Foo):
def __init__(self, value):
super(Bar, self).__init__()
class Baz(Bar):
VALUE = 1
Скорее всего, что угодновы на самом деле пытаетесь достичь, может быть сделано лучше, не требуя ни одного из этих изменений.Но так как ваш игрушечный пример ничего не дает, больше нечего показать.