У меня есть пользовательские enum
, MyEnum
, в которых некоторые элементы имеют разные имена, но одинаковое значение.
from enum import Enum
class MyEnum(Enum):
A = 1
B = 2
C = 3
D = 1 # Same value as A
Следовательно, list(MyEnum)
возвращает только имена некоторых членов (первое имя для каждого значения):
>>>list(MyEnum)
[<MyEnum.A: 1>, <MyEnum.B: 2>, <MyEnum.C: 3>]
Судя по всему, list(MyEnum.__members__)
возвращает все имена:
>>>list(MyEnum.__members__)
['A', 'B', 'C', 'D']
Однако, если я попытаюсь переопределить метод __iter__()
для моего перечисления, переопределение, похоже, не удастся:
class MyEnum(Enum):
A = 1
B = 2
C = 3
D = 1 # Same value as A
@classmethod # an attempt to override list(MyEnum) that doesn't change anything
def __iter__(cls):
return iter(list(cls.__members__))
Судя по всему, list(MyEnum)
никогда не попадает в обычай __iter__()
(на что указывает, скажем, добавление print()
перед возвращением в наш кастом __iter__()
).
Почему это?
Как я могу переопределить поведение list(MyEnum)
по умолчанию, чтобы получить все разные имена?
🤔 А знаете ли вы, что...
Синтаксис Python известен своей простотой и читаемостью.
Метод класса — это не то же самое, что метод экземпляра метакласса, которым является __iter__
для Enum
. Вам необходимо определить новый метакласс, который вы можете использовать для определения нового подкласса Enum
, который делает то, что вы ищете.
Предостережение: я не утверждаю, что замена текущего поведения EnumType.__iter__
вашим предложением будет совместима с текущей семантикой Enum
, но это сделает ваше определение доступным.
from enum import EnumType, Enum
class MyEnumType(EnumType):
def __iter__(self):
# Must return an Iterator, something with a __next__ method,
# not an Iterable.
return iter(list(self.__members__))
class MyEnumBase(Enum, metaclass=MyEnumType):
pass
class MyEnum(MyEnumBase):
A = 1
B = 2
C = 3
D = 1
assert list(MyEnum) == ['A', 'B', 'C', 'D']