如何创建使用成员名称作为值的枚举?

时间:2014-06-14 19:44:50

标签: python python-3.x enums

我想简化以下类,这样我就不需要为每个元素键入值,而是使用枚举成员的名称。这类似于文档中的AutoNumber example

class Screen(Enum):
    MAIN = 'main'
    OPTIONS = 'options'
    GAME = 'game'
    SCORE = 'score'

而不是上述内容,我想做以下事情,以便例如Screen.MAIN'main'

class Screen(AutoNameValueEnum):
    MAIN = ()
    OPTIONS = ()
    GAME = ()
    SCORE = ()

我尝试修改链接的示例,但我无法弄清楚如何获取枚举成员的名称。

2 个答案:

答案 0 :(得分:3)

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 = ()

此备选方案的更新示例。总而言之,我认为使用功能界面suggested here是最干净的解决方案,因为您可以确保在使用它时没有任何中断。

答案 1 :(得分:3)

<强>更新

Python 3.6和aenum 2.0有一个新方法可以被覆盖,以允许枚举成员的自定义值使这个过程变得非常简单:

def _generate_next_value_(name, start, count, last_values):
    return name
  • name是会员的名称
  • start是枚举的起始值(默认为1
  • count是目前为止的成员数
  • last_values是目前为止的成员值列表

使用class方法*无法实现此目的,但您可以使用Functional API

Color = enum.Enum(
    'Color',
    ((name, name.lower()) for name in 'BLACK RED GREEN BLUE'.split()),
    )

*好的,像Python中的大多数事情一样,如果你努力尝试就可以,但为什么要去做所有额外的工作呢?