提问人:KamilCuk 提问时间:9/26/2023 最后编辑:KamilCuk 更新时间:10/11/2023 访问量:103
如何静态防止 str == 枚举比较?
How to statically protect against str == enum comparisons?
问:
我经常犯以下错误:
import enum
class StatusValues(enum.Enum):
one = "one"
two = "two"
def status_is_one(status: str):
return status == StatusValues.one
String 永远不会是枚举类。问题是它应该是.StatusValues.one.value
是否有 -ish 函数,以便我的 pyright 会在我将字符串与类进行比较的行上出错?有没有很好的方法可以防止此类错误?strcmp(status, StatusValues.one)
答:
5赞
plamut
9/26/2023
#1
是的,这可能是一个问题:默认情况下,我们不能直接将字符串与枚举成员进行比较:
>>> status = "two"
>>> status == StatusValues.two
False
必须记住将字符串与枚举成员的字符串进行比较,这也有点冗长:.value
>>> "two" == StatusValues.two.value
True
幸运的是,有一个解决方案,甚至在文档中也提到过,但它曾经(在 Python 3.11 之前)在一个有点容易错过的部分(恕我直言)中。我们可以混合一种类型的枚举成员:
class IntEnum(int, Enum):
pass
这演示了如何定义相似的派生枚举;例如,混合而不是 .
str
int
因此,解决方案是定义一个具有基类的枚举:str
class StatusValues(str, Enum):
one = "one"
two = "two"
>>> status = "two"
>>> status == StatusValues.two # no .value
True
在 Python 3.11+ 中,StrEnum 已经包含在模块中,但您提到您仍然需要支持 Python 3.7。enum
评论
0赞
jonrsharpe
9/26/2023
请注意,这些混合枚举并不总是以可预测的方式运行: stackoverflow.com/q/77153859/3001761
0赞
plamut
9/26/2023
有趣,谢谢你的分享!幸运的是,这似乎是一个边缘案例,被 Enum 作者本人所劝阻,但还是很高兴了解它。
0赞
KamilCuk
9/27/2023
这是一个非常有用的答案。尽管多次阅读文档,但我不知道您可以同时从 str 和 Enum 继承来实现此行为。做 3.7 可移植性类非常容易,看起来像class MyStrEnum(str, Enum): def _generate_next_value_(name, *args): return name
0赞
plamut
9/27/2023
事实上,这正是我在几个项目中使用的(示例)。这样的类甚至在键入枚举成员的值时避免了重复(例如),我们可以说,保护我们免受字符串值中的拼写错误。foo = 'foo'
foo = enum.auto()
评论
class StatusValues(str, enum.Enum):
enum.StrEnum
status = "one"; status == StatusValues.one
str