如何创建一个以成员名称为值的枚举?
我想简化下面这个类,这样我就不需要为每个元素都输入值,而是可以直接使用枚举成员的名字。这有点像文档中的AutoNumber示例。
class Screen(Enum):
MAIN = 'main'
OPTIONS = 'options'
GAME = 'game'
SCORE = 'score'
我想用下面的方式来实现,比如说Screen.MAIN
的值是'main'
:
class Screen(AutoNameValueEnum):
MAIN = ()
OPTIONS = ()
GAME = ()
SCORE = ()
我尝试修改链接中的示例,但我搞不清楚怎么才能获取枚举成员的名字。
2 个回答
4
更新
在Python 3.6和aenum 2.0
中,新增了一种方法,可以让你自定义枚举成员的值,这样做起来就简单多了:
def _generate_next_value_(name, start, count, last_values):
return name
name
是成员的名字start
是枚举的起始值(默认是1
)count
是目前为止成员的数量last_values
是到目前为止成员的值的列表
你不能通过class
方法来实现这一点,但可以使用功能性API来做到:
Color = enum.Enum(
'Color',
((name, name.lower()) for name in 'BLACK RED GREEN BLUE'.split()),
)
*好吧,像Python中的大多数事情一样,如果你足够努力,确实可以做到,但何必费那么大劲呢?
4
在一个Enum
(枚举)中,成员本身也是Enum
。文档中的例子使用了成员的__new__
方法来给它们赋值。不过,你不能用这个方法,因为新的成员并不知道它是如何在它所属的类中被调用的。相反,你应该使用初始化器。下面是一个例子:
>>> class AutoNameValueEnum(enum.Enum):
... def __init__(self):
... self._value_ = self._name_.lower()
...
>>> class Color(AutoNameValueEnum):
... RED = ()
...
>>> Color.RED
<Color.RED: 'red'>
更新:
请注意,使用这个解决方案后,值的查找将不再可能。这是因为枚举的元类在调用初始化器之前就存储了值。这会导致你无法将枚举进行序列化,也可能在其他地方出现问题。一个替代方案(虽然会破坏与类似字符串的等价性,比如a is "foo"
,但其他方面不会受影响)是使用不可哈希的类型作为值。这样,枚举类就会进行线性搜索,而不是通过映射查找值的键。
class UnhashableString(str):
def __hash__(self):
raise TypeError
class AutoNameValueEnum(enum.Enum):
def __init__(self):
self._value_ = UnhashableString(self._name_.lower())
class Color(AutoNameValueEnum):
RED = ()
这是这个替代方案的更新例子。总的来说,我认为使用这里建议的功能接口是最干净的解决方案,因为你可以确保在使用它时不会出现问题。