如何在枚举类型中定义枚举成员的映射?

时间:2016-05-12 10:03:32

标签: python-3.x enums metaclass

我有一个像这样的Python枚举:

from enum import Enum, unique

@unique
class Levels(Enum):
  Unknown = 0
  Warning = 1
  Error =   2

  def __eq__(self, other):    return self.value ==  other.value
  def __ne__(self, other):    return self.value !=  other.value
  def __lt__(self, other):    return self.value <   other.value
  def __le__(self, other):    return self.value <=  other.value
  def __gt__(self, other):    return self.value >   other.value
  def __ge__(self, other):    return self.value >=  other.value

  __MAPPING__ = {
    "warn":   Warning,
    "error":  Error
  }

  @classmethod
  def Parse(cls, value, default=None):
    return cls.__MAPPING__.get(value, default)

在这个例子中,我已经将映射提取到一个类成员中(根据timeit.timeit(),它更快)。

我现在的问题是,dict值使用原始枚举成员值(整数)而不是创建的枚举成员(EnumMeta)。这是合理的,因为在构造字典时不存在。

如何/我在哪里可以挂钩到Enum类/ EnumMeta类或我自己的Levels类,用创建的枚举成员修补dict?

2 个答案:

答案 0 :(得分:1)

[仅显示相关内容......]

@unique
class Levels(Enum):
    Unknown = 0
    Warning = 1
    Error =   2

    __MAPPING__ = {
        "warn":   Warning,
        "error":  Error
   }

    def __init__(self, *args):
        """Patch the embedded MAP dictionary"""
        self.__class__.__MAPPING__[self._name_] = self
每个成员创建后都会调用

__init__,因此此时您可以使用成员名称作为密钥更新__MAPPING__。如果你经常使用这种模式,你应该考虑使用另一个装饰器:

def add_mapping(enum_cls):
    for name in enum_cls.__MAPPING__:
        member = enum_cls.__members__[name]
        enum_cls.__MAPPING__[name] = member
    return enum_cls

并在使用中:

@add_mapping
@unique
class Levels(Enum):
    Unknown = 0
    Warning = ...

答案 1 :(得分:1)

构建Mr. Furman's提供above,使用map_value(name)方法获取映射:

add_mapping(enum_cls): 
    enum_cls.__MAPPING__ = {e.value: e for e in enum_cls}
    enum_cls.map_value = lambda name, default=None: enum_cls.__MAPPING__.get(name, default)
    return enum_cls