用 Enum 替代字符串或数字常量可锁死合法取值、支持 IDE 补全与类型检查、防止拼写错误和非法赋值;推荐显式命名+唯一不可变值,避免数字枚举和重复值;需注意 is 比 == 更安全、类型提示增强可靠性;序列化/反序列化及 ORM 映射需显式转换,不同框架对 .name/.value 使用不一致,须统一封装。

为什么用 Enum 替代字符串或数字常量
直接写 "pending" 或 0 表示订单状态,后期改名、拼错、传错值都难发现。而 Enum 把合法取值锁死在类定义里,IDE 能自动补全,类型检查工具(如 mypy)能报错,运行时也能防止非法赋值。
比如把 status = "pendng"(多打一个 n)这种低级错误,提前拦在开发阶段。
Enum 的基础写法与常见误用
别用 class Status(Enum): pending = 0; shipped = 1 这种纯数字枚举——语义弱,且容易和整数运算混淆(比如 status == 0 会意外为真)。推荐显式命名 + 唯一值:
class OrderStatus(Enum): PENDING = "pending"; SHIPPED = "shipped"- 值用字符串、元组甚至对象都行,但别用可变对象(如
list)作值,否则实例不可哈希 - 不要给枚举成员赋重复值(
A = 1; B = 1),否则B是A的别名,不是独立成员
在类属性和方法中安全使用 Enum
把 Enum 当字段类型用,比注释或文档更可靠:
立即学习“Python免费学习笔记(深入)”;
from enum import Enum
<p>class OrderStatus(Enum):
PENDING = "pending"
SHIPPED = "shipped"</p><p>class Order:
def <strong>init</strong>(self, status: OrderStatus):
self.status = status # 类型提示 + 运行时约束</p><pre class="brush:php;toolbar:false;">def can_cancel(self) -> bool:
return self.status is OrderStatus.PENDING
注意:is 比 == 更安全(避免重载 __eq__ 导致意外行为);类型提示让 IDE 和静态检查器真正起作用;构造时传 "pending" 会直接抛 ValueError,而不是静默接受。
兼容 JSON 序列化与数据库映射的坑
Enum 实例不能直接 json.dumps(),也不被 SQLAlchemy 或 Django ORM 原生支持。必须显式转换:
- 序列化:用
order.status.value(得字符串)或order.status.name(得"PENDING") - 反序列化:用
OrderStatus(data["status"])或OrderStatus[data["status"]](后者按 name 查,前者按 value 查) - ORM 映射:SQLAlchemy 推荐用
Enum(OrderStatus)类型,并设create_constraint=True;Django 用choices配合get_FOO_display(),但丢失类型安全
最易忽略的是:不同框架对 Enum 的默认行为不一致,同一个枚举类在 API 返回、数据库存取、日志打印时可能需要不同访问方式(.name vs .value),得统一约定并在项目里封装好转换逻辑。


















