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

bli*_*bli 29 python enums python-3.6

我刚刚发现python中存在一个Enum基类,我试图想象它对我有用.

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

from enum import Enum, auto

class Signal(Enum):
    red = auto()
    green = auto()
    orange = auto()
Run Code Online (Sandbox Code Playgroud)

假设我从程序中的某个子系统接收信息,例如以表示颜色名称的字符串的形式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.

bli*_*bli 35

一个不创建枚举实例.该Signal(foo)语法用于按值访问Enum成员,这些成员不打算使用它们auto().

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

Signal[brain_detected_colour] is Signal.red
Run Code Online (Sandbox Code Playgroud)

另一种可能性是将字符串与nameEnum成员进行比较:

# Bad practice:
brain_detected_colour is Signal.red.name
Run Code Online (Sandbox Code Playgroud)

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

# Better practice:
brain_detected_colour == Signal.red.name
Run Code Online (Sandbox Code Playgroud)

(由于字符串实习,字符串之间的身份比较有效,最好不要依赖.感谢@mwchase和@Chris_Rands让我意识到这一点.)

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

class Signal(Enum):
    red = "red"
    green = "green"
    orange = "orange"
Run Code Online (Sandbox Code Playgroud)

(有关将此方法自动化的方法,请参阅此答案.)

然后,Signal(brain_detected_colour) is Signal.red将是有效的.

  • 在`brain_detected_colour中使用`is`是Signal.red.name`是有风险的; 最好使用`==`. (7认同)
  • 你依赖于字符串实习,黑暗的实现细节http://guilload.com/python-string-interning/,永远不要使用`is`除非你真的需要比较对象的身份 (4认同)
  • @mwchase 你能解释一下原因吗,以便我可以编辑我的答案并添加解释? (2认同)
  • 解决了我的问题.虽然我不能使用`Signal(brain_detected_colour)是Signal.red`(在答案的最后提到,当用字符串值构建枚举时)......`Signal [brain_detected_colour] == Signal.red`确实有效然而.请注意,我考虑了评论说使用`==`进行比较风险较小. (2认同)

Mus*_*waz 32

更好的做法是继承Signalstr

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

brain_detected_colour = 'red'
brain_detected_colour == Signal.red  # direct comparison
Run Code Online (Sandbox Code Playgroud)

  • 以防万一您仍然有兴趣了解为什么最好使用 mixin str https://docs.python.org/3/library/enum.html#others (8认同)
  • @OlimjonIbragimov 当您使用普通的“Enum”时,您需要这样做。但是,当您混合使用“str”时,例如:“class Signal (str, Enum):”,那么您就不需要这样做。 (4认同)
  • 您能在答案中解释一下为什么这是更好的做法吗? (2认同)
  • 这对我有用。@MartinGrey,这可能是因为您将“string”类型与“enum”类型进行比较。当枚举类中不存在“str”时,我正在对字符串与枚举进行比较。(我猜分配字符串值是不够的。) (2认同)

Eth*_*man 11

可以auto()返回枚举成员的名称作为其值(auto在文档1部分中:

>>> 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'>]
Run Code Online (Sandbox Code Playgroud)

1这需要版本Python 3.6或aenum2.0 2(aenum与Pythons一样长到2.7).

2披露:我是Python stdlibEnum,enum34backportAdvanced Enumeration(aenum) 库的作者.

  • 不幸的是,尽管以下断言失败: `assert Ordinal.NORTH == "NORTH"` 所以您不能直接与字符串进行比较。编辑:哦,这可以通过使用“class Ordinal(str, AutoName)”来工作。 (5认同)