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

Python 3.x 如何在枚举类型中定义枚举成员的映射?,python-3.x,enums,metaclass,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 de

我有这样一个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)
从枚举导入枚举,唯一
@独特的
类别级别(枚举):
未知=0
警告=1
误差=2
def _eq _(self,other):返回self.value==other.value
定义(self,other):返回self.value!=其他价值
def uu lt uu(self,other):返回self.value=other.value
__映射{
“警告”:警告,
“错误”:错误
}
@类方法
def解析(cls,值,默认值=无):
返回cls.\uuuuu映射\uuuuu.get(值,默认值)
在本例中,我已经将映射提取到类成员中(根据
timeit.timeit()
,它的速度更快)

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


如何/在何处连接到Enum类/EnumMeta类或我自己的Levels类,以使用创建的Enum成员修补dict?[仅显示相关部分…]

@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
\uuuuu init\uuuuu
是在创建每个成员后为其调用的,因此此时您可以使用成员名称作为键来更新
\uuuuuu映射。如果你使用这个图案很多,你应该考虑使用另一个装饰器:

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 = ...
要在提供的基础上构建映射,请使用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 

我对您的解决方案做了一点改进,因为预期的枚举成员是dict中的值。因此,每次初始化调用都会扫描dict,并用枚举成员替换值(int)(如果在映射中定义)。@Paebbels:啊,我误解了这一部分。简化了代码并更新了装饰程序。@Paebbels:如果这只是性能增强,为什么不加入所有成员?此外,在3.5中,大部分(如果不是全部的话)的性能命中被删除。@martineau:Ah,OP有额外的
P
打字错误,我只成功地复制了一次。@martineau:Correct,
\u name
不是参数,在调用
\u init\u
时它已经是成员的一部分。(因此是领先的
self.
;-))。它是由元类设置的。我批准了您对我的答案的编辑,谢谢您的关注。现在,如果我们能让编辑不拒绝对他们不理解的代码进行错误修复:(