问题扩展枚举并重新定义__getitem__

时间:2014-07-12 19:49:56

标签: python-3.x enums

我在__getitem__的自定义子类上重新定义Enum时遇到了一些麻烦。我的__getitem__没有被调用。我想它与Enum的元类有关,但我不确定是什么和为什么。

最小工作示例(Python 3.4):

from enum import Enum, unique

@unique
class Test(Enum):
    a = "a"
    b = "b"

    def __getitem__(self, name):
        try:
            return super().__getitem__(name)
        except (TypeError, KeyError) as error:
            print("TEST")

if __name__ == "__main__":
    Test["a"]
    Test["c"]

结果:

$ python test.py
Traceback (most recent call last):
  File "test.py", line 18, in <module>
    Test["c"]
  File "C:\Development\Python\Python34\lib\enum.py", line 258, in __getitem__
    return cls._member_map_[name]
KeyError: 'c'

3 个答案:

答案 0 :(得分:7)

正如@ shx2指出的那样,你没有调用__getitem__()子类的Enum。以下是如何通过子类化Enum的元类:

来解决这个问题
from enum import Enum, EnumMeta, unique

class TestEnumMeta(EnumMeta):
    def __getitem__(self, name):
        try:
            return super().__getitem__(name)
        except (TypeError, KeyError) as error:
            print("TEST")

@unique
class Test(Enum, metaclass=TestEnumMeta):
    a = "a"
    b = "b"

if __name__ == "__main__":
    Test["a"]
    Test["c"] --> TEST

答案 1 :(得分:6)

如果您在__getitem__实例上使用方括号,则会调用Enum的覆盖。

Test["A"]一样访问它会调用元类的__getitem__方法。因此,在您的情况下,您需要继承EnumMeta元类,重写其__getitem__,然后使用该元类创建自己的枚举类。

您可以查看源代码here

答案 2 :(得分:0)

这是我从 ts 了解到的在 Python 中使用枚举的答案:

from enum import Enum, EnumMeta, unique
class TestEnumMeta(EnumMeta):
    def __getitem__(self, indexOrName):
        if isinstance(indexOrName, str):
            return super().__getitem__(indexOrName).value
        elif isinstance(indexOrName, int) and indexOrName < super().__len__():
            return list(self)[indexOrName].name


@unique
class Model(Enum, metaclass=TestEnumMeta):
    pass

您现在可以像这样使用它:

Test(Model):
   type0=0
   type1=1

>>> Test['type0']
0
>>> Test[0]
type0