如何将字符串与 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.red
是False
,因为Signal.red
不是字符串。
Signal(brain_detected_colour) is Signal.red
失败 ValueError: 'red' is not a valid Signal
。
一个人不会创建 instance of an Enum。
Signal(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
我刚刚在 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.red
是False
,因为Signal.red
不是字符串。
Signal(brain_detected_colour) is Signal.red
失败 ValueError: 'red' is not a valid Signal
。
一个人不会创建 instance of an Enum。
Signal(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