如何定义枚举类型中枚举成员的映射?
Posted
技术标签:
【中文标题】如何定义枚举类型中枚举成员的映射?【英文标题】:How to define a mapping of enum members in the enum type? 【发布时间】:2016-09-08 02:13:49 【问题描述】:我有一个这样的 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)。这是合理的,因为在构造 dict 时不存在。
我如何/在哪里可以挂钩到 Enum 类/EnumMeta 类或我自己的 Levels 类,以使用创建的枚举成员修补字典?
【问题讨论】:
【参考方案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 = ...
【讨论】:
我稍微改进了你的解决方案,因为预期的枚举成员是字典中的值。因此,每个 init 调用都会扫描 dict 并用枚举成员替换一个值 (int)(如果在映射中定义)。 @Paebbels:啊,我误解了那部分。简化了您的代码并更新了装饰器。 @Paebbels:如果这只是性能提升,为什么不让所有成员都加入?此外,在 3.5 中,大部分(如果不是全部)性能影响已被移除。 @martineau:啊,OP有额外的P
错字,我只成功地复制了一次错字。
@martineau:正确,_name_
不是参数,在调用 __init__
时它已经是成员的一部分。 (因此领先self.
;-))。它由元类设置。【参考方案2】:
以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
【讨论】:
我批准了您对我的回答的编辑,感谢您接受。现在,如果我们可以让编辑人员不要拒绝对他们不理解的代码进行错误修复。 :(以上是关于如何定义枚举类型中枚举成员的映射?的主要内容,如果未能解决你的问题,请参考以下文章