如何将字符串与 python 枚举进行比较?

How to compare a string with a python enum?

我刚刚在 python 中发现了 Enum 基 class 的存在,我正在想象它对我有何用处。

假设我定义了一个红绿灯状态:

from enum import Enum, auto

class Signal(Enum):
    red = auto()
    green = auto()
    orange = auto()

假设我从我的程序中的某个子系统接收信息,以表示颜色名称的字符串的形式,例如 brain_detected_colour = "red".

如何将此字符串与我的交通灯信号进行比较?

很明显,brain_detected_colour is Signal.redFalse,因为Signal.red不是字符串。

Signal(brain_detected_colour) is Signal.red 失败 ValueError: 'red' is not a valid Signal

一个人不会创建 instance of an EnumSignal(foo) 语法用于按值访问 Enum 成员,当它们是 auto().

时不打算使用它们

但是可以使用字符串 access Enum members 就像访问 dict 中的值一样,使用方括号:

Signal[brain_detected_colour] is Signal.red

另一种可能性是将字符串与枚举成员的 name 进行比较:

# Bad practice:
brain_detected_colour is Signal.red.name

但在这里,我们不是在测试 Enum 成员之间的身份,而是在比较字符串,因此最好使用相等性测试:

# Better practice:
brain_detected_colour == Signal.red.name

(由于 string interning,字符串之间的身份比较起作用了,最好不要依赖它。感谢 @mwchase 和 @Chris_Rands 让我意识到这一点。)

另一种可能性是在创建枚举时将成员值显式设置为其名称:

class Signal(Enum):
    red = "red"
    green = "green"
    orange = "orange"

(请参阅 以了解自动执行此操作的方法。)

那么,Signal(brain_detected_colour) is Signal.red就有效了。

可以将 auto() return 枚举成员的名称作为其值(在 auto section of the docs1 :

class AutoName(Enum):
    def _generate_next_value_(name, start, count, last_values):
        return name

class Ordinal(AutoName):
    NORTH = auto()
    SOUTH = auto()
    EAST = auto()
    WEST = auto()

正在使用:

>>> list(Ordinal)
[<Ordinal.NORTH: 'NORTH'>, <Ordinal.SOUTH: 'SOUTH'>, <Ordinal.EAST: 'EAST'>, <Ordinal.WEST: 'WEST'>]

1 这需要版本 Python 3.6,或 aenum 2.02 (aenum与 Pythons 一样老到 2.7)。

2 披露:我是 Python stdlib Enum, the enum34 backport, and the Advanced Enumeration (aenum) 库的作者。

更好的做法是从 str 继承 Signal:

class Signal(str, Enum):
    red = 'red'
    green = 'green'
    orange = 'orange'

brain_detected_colour = 'red'
brain_detected_colour == Signal.red  # direct comparison
class Signal(Enum):
    red = auto()
    green = auto()
    orange = auto()

    def equals(self, string):
       return self.name == string

brain_detected_colour = "red"

if Signal.red.equals(brain_detected_colour):
   #something awesome