Python 的 Enum:别再让散落的字符串常量满天飞

举报
yd_268445051 发表于 2026/11/06 09:57:50 2026/11/06
【摘要】 Python 的 Enum:别再让散落的字符串常量满天飞写 Python 代码时,最容易悄悄长出来的技术债,就是散落在各处的字符串常量:"pending"、"paid"、"shipped",今天在订单模块写一遍,明天在报表里又写一遍。拼错一个字母不会报错,只会在运行时悄悄走错分支,等发现时往往已经是一笔错账。Enum 正是用来收拢这些常量的:把一组相关的取值收进一个类型里,让拼写错误在写代...

Python 的 Enum:别再让散落的字符串常量满天飞

写 Python 代码时,最容易悄悄长出来的技术债,就是散落在各处的字符串常量:"pending"、"paid"、"shipped",今天在订单模块写一遍,明天在报表里又写一遍。拼错一个字母不会报错,只会在运行时悄悄走错分支,等发现时往往已经是一笔错账。

Enum 正是用来收拢这些常量的:把一组相关的取值收进一个类型里,让拼写错误在写代码时就暴露出来。

from enum import Enum

class OrderStatus(Enum):
    PENDING = "pending"
    PAID = "paid"
    SHIPPED = "shipped"

这样一来,代码里不再直接写 "paid",而是写 OrderStatus.PAID。写错成 OrderStatus.PAIID 会立刻报 AttributeError,编辑器也能自动补全;写错字符串却什么提示都没有,只能靠测试或线上事故发现。

第二个好处是比较更安全。字符串比较靠的是值相等,"Paid" 和 "paid" 就不是同一个状态,大小写一混就出问题。枚举成员是单例,is 比较就够了:

if order.status is OrderStatus.PAID:
    send_receipt(order)

第三个要点是取值与展示要分开。枚举成员的 .value 是存进数据库或发给接口的值,.name 是代码里的名字,两者不必相同:

class OrderStatus(Enum):
    PENDING = "pending"

print(OrderStatus.PENDING.value)  # pending
print(OrderStatus.PENDING.name)   # PENDING

入库时存 .value,读出来再用 OrderStatus(value) 还原成成员;如果库里出现了一个不在枚举里的旧值,OrderStatus(value) 会直接报 ValueError,这反而是好事——脏数据在边界就被拦住,而不是带着一个谁也不认识的状态一路往下跑。

还有一个实用技巧:需要按顺序比较的状态,可以用 IntEnum,让成员同时是一个整数:

from enum import IntEnum

class Priority(IntEnum):
    LOW = 1
    NORMAL = 2
    HIGH = 3

assert Priority.HIGH > Priority.LOW

但要注意,IntEnum 的成员和整数可以直接比较、也可以混进算术运算,这既是方便也是口子:不希望被当成数字用的状态,就老老实实用普通的 Enum,别为了图省事都换成 IntEnum。

最后说一个常见坑:不要在枚举成员里放可变对象,也不要给枚举加太多行为。枚举的职责是“把取值收拢、把名字定死”,状态流转的规则——比如已发货的订单能不能退回待支付——应该写在单独的函数里,而不是塞进枚举的方法中,否则枚举很快又会变成另一个什么都管的大类。

总结一下:字符串常量适合只出现一次的临时值,一旦某个取值会在两个以上的地方出现,就把它收进 Enum;比较用 is,入库用 .value,读库用 OrderStatus(value) 还原并让非法值尽早报错。把名字定死,拼写错误就从运行时事故变成了写代码时的即时提醒。

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0)

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。