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

问题描述:

我有一个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 

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

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

在本例中,我已经提取出的映射到一个类的成员(根据timeit.timeit(),其更快)。

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

如何/在哪里可以钩入Enum类/ EnumMeta类或我自己的Levels类,以便使用创建的枚举成员修补字典?

[只显示相关的片...]

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

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

    def __init__(self, *args): 
     """Patch the embedded MAP dictionary""" 
     self.__class__.__MAPPPING__[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 = ... 
+0

我改进了一点你的解决方案,因为,预期的枚举成员是字典中的值。因此,如果在映射中定义了每个__init__调用,则会扫描该词典并用枚举成员替换值(int)。 – Paebbels

+1

@帕培尔:啊,我误解了那部分。简化你的代码并更新装饰器。 –

+0

@Paebbels:如果这仅仅是一个性能增强,为什么你不把所有的成员?而且,在3.5中,大部分(如果不是全部)性能命中被删除。 –

要建立在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 
+0

我批准了你的编辑到我的答案,谢谢你的捕捉。现在,如果我们可以让编辑不拒绝错误修复代码,他们不明白。 :( –