Python 的 enum 枚举怎么用?和用常量、字符串有什么区别?
简化版
**enum.Enum 是 Python 的「枚举」——把一组「有限的、命名的常量」定义成一个类,每个成员既有「名字(name)」又有「值(value)」,比裸用整数/字符串常量更安全、更可读、更不易出错。**用法:继承 Enum,把成员写成类属性:class Color(Enum): RED = 1; GREEN = 2; BLUE = 3,然后 Color.RED(成员)、Color.RED.name(‘RED’)、Color.RED.value(1)。相比裸常量的好处:① 类型安全——Color.RED 是一个独立的枚举成员,不会和别的整数/字符串意外相等或混用(Color.RED == 1 为 False,而裸常量 RED = 1 就等于任意的 1);② 可读——打印是 Color.RED 而非无意义的 1;③ 成员唯一、可迭代(for c in Color)、可用 in 判断、能当字典键;④ 防止无效值(Color(5) 抛 ValueError)。常用变体:IntEnum(成员也是 int、能和整数比较运算,兼容旧接口)、StrEnum(3.11+,成员也是 str)、Flag/IntFlag(位标志、可 | 组合)、auto()(自动赋值)。核心记忆:Enum 把命名常量组织成类(有 name/value、类型安全、可迭代、成员唯一),比裸常量安全可读;要和 int/str 兼容用 IntEnum/StrEnum,位标志用 Flag。
详细版
Enum 的用法:
| 特性 | 说明 |
|---|---|
class C(Enum): A = 1 | 定义枚举 |
C.A | 成员(不是值) |
C.A.name / C.A.value | 名字 ‘A’ / 值 1 |
C(1) / C['A'] | 按值 / 按名查找成员 |
for m in C | 可迭代(按定义顺序) |
auto() | 自动赋值(1, 2, 3…) |
IntEnum / StrEnum | 成员兼是 int / str |
Flag / IntFlag | 位标志(可 | 组合) |
from enum import Enum, IntEnum, Flag, auto
# 基本枚举
class Color(Enum):
RED = 1
GREEN = 2
BLUE = 3
print(Color.RED) # Color.RED(可读)
print(Color.RED.name) # 'RED'
print(Color.RED.value) # 1
print(Color(1)) # Color.RED(按值查找)
print(Color['RED']) # Color.RED(按名查找)
# 类型安全:不会和裸整数混
print(Color.RED == 1) # False(枚举成员 != 整数)
print(Color.RED == Color.RED) # True(身份唯一)
# 可迭代、in 判断、当字典键
for c in Color:
print(c.name, c.value) # RED 1 / GREEN 2 / BLUE 3
print(Color.RED in Color) # True
d = {Color.RED: "红色"} # 能当字典键
# 无效值报错
# Color(5) # ✗ ValueError(防止无效值)
# auto() 自动赋值
class Status(Enum):
PENDING = auto() # 1
RUNNING = auto() # 2
DONE = auto() # 3
# IntEnum:成员也是 int,能和整数比较/运算
class Priority(IntEnum):
LOW = 1
HIGH = 10
print(Priority.HIGH > Priority.LOW) # True
print(Priority.HIGH == 10) # True(IntEnum 和 int 相等)
print(Priority.LOW + 5) # 6(能参与运算)
# Flag:位标志,可组合
class Perm(Flag):
READ = auto() # 1
WRITE = auto() # 2
EXEC = auto() # 4
rw = Perm.READ | Perm.WRITE
print(Perm.READ in rw) # True
⚠️ 核心价值:枚举把「散落的魔法常量」收拢成一个「有类型、有名字、成员唯一」的集合,用
Color.RED代替裸的1或"red",从而获得类型安全(不会误传别的值)、可读性(打印/调试看得懂)、和一组内建能力(迭代、成员判断、防无效值)。裸常量的问题很实际:STATUS_ACTIVE = 1、STATUS_DELETED = 2散落在代码里,函数收到个2你不知道它是状态、优先级还是别的;传错值(set_status(5))也没人拦;打印日志看到1一头雾水。枚举一次解决:Status.ACTIVE自解释、Status(5)直接 ValueError、for s in Status能遍历所有合法值。关键取舍是「要不要和 int/str 兼容」:纯Enum最安全(成员不等于任何 int/str,Color.RED != 1),但和需要「原始值」的旧接口(数据库存整数、JSON 传字符串)对接麻烦;这时用IntEnum(成员就是 int、能直接比较运算和序列化)或StrEnum(3.11+,成员就是 str),牺牲一点安全换兼容性。位标志(可读写权限组合)用Flag/IntFlag。
完整版教学
一、为什么需要枚举
先理解裸常量的问题、枚举解决什么:
裸常量的问题:
# 用模块级常量表示状态
STATUS_PENDING = 1
STATUS_ACTIVE = 2
STATUS_DELETED = 3
痛点:
① 没有类型——函数收到 2,不知是状态/优先级/其他
def process(status): ... # status 就是个 int,能传任何数
② 无效值不拦——process(99) 照样跑(99 没意义)
③ 可读性差——日志/调试看到 2,不知含义
④ 散落——常量分散,没有"这是一组"的归属
⑤ 易混——STATUS_ACTIVE=2 和 PRIORITY_HIGH=2 意外相等
枚举的解决:
from enum import Enum
class Status(Enum):
PENDING = 1
ACTIVE = 2
DELETED = 3
✓ 有类型:Status.ACTIVE 是 Status 类型
✓ 防无效:Status(99) → ValueError
✓ 可读:打印 Status.ACTIVE(自解释)
✓ 归组:一个类装一组相关常量
✓ 不混:Status.ACTIVE != Priority.HIGH(不同枚举不相等)
✓ 附加能力:迭代、成员判断、当字典键
所以枚举解决裸常量的:无类型/无效值不拦/不可读/散落/易混,提供类型安全的命名常量组
裸常量的问题:模块级常量 STATUS_PENDING = 1 等——痛点是① 没有类型(函数收到 2 不知是状态还是别的)、② 无效值不拦(process(99) 照样跑)、③ 可读性差(日志看到 2 不知含义)、④ 散落(没有「这是一组」的归属)、⑤ 易混(STATUS_ACTIVE=2 和 PRIORITY_HIGH=2 意外相等)。枚举的解决:class Status(Enum): PENDING = 1; ...——✓ 有类型(Status.ACTIVE 是 Status 类型)、✓ 防无效(Status(99) ValueError)、✓ 可读(打印 Status.ACTIVE 自解释)、✓ 归组、✓ 不混(不同枚举不相等)、✓ 附加能力(迭代/成员判断/当字典键)。理解「裸常量问题:无类型/无效值不拦/不可读/散落/易混;枚举提供类型安全的命名常量组(有类型+防无效+可读+归组+不混+附加能力)」,就理解了为什么需要枚举。
二、Enum 的基本用法
理解定义和访问枚举:
定义枚举:继承 Enum,成员作类属性
from enum import Enum
class Color(Enum):
RED = 1
GREEN = 2
BLUE = 3
成员的三个属性:
Color.RED # 成员本身(Color.RED)
Color.RED.name # 名字 'RED'(字符串)
Color.RED.value # 值 1
两种查找方式:
Color(1) # 按"值"查找 → Color.RED
Color['RED'] # 按"名字"查找 → Color.RED
→ 值查找用于反序列化(存的是值,还原成成员)
成员是"单例"(唯一):
Color.RED is Color.RED # True(每个成员全局唯一)
Color(1) is Color.RED # True(值查找返回同一个成员)
→ 可以放心用 is 比较
迭代(按定义顺序):
for c in Color:
print(c) # Color.RED, Color.GREEN, Color.BLUE
list(Color) # [Color.RED, ...]
成员判断:
Color.RED in Color # True
1 in Color # False(值不是成员,注意)
Color(1) in Color # True
当字典键(成员可哈希):
colors = {Color.RED: "红", Color.GREEN: "绿"}
所以定义继承 Enum、成员作类属性;.name/.value 取名和值;C(值)/C['名']查找;成员唯一可 is
定义枚举:继承 Enum、成员作类属性(class Color(Enum): RED = 1; ...)。成员的三个属性:Color.RED(成员本身)、Color.RED.name(名字 ‘RED’)、Color.RED.value(值 1)。两种查找方式:Color(1)(按值查找)、Color['RED'](按名字查找)——值查找用于反序列化(存的是值、还原成成员)。成员是「单例」(唯一):Color.RED is Color.RED 为 True、Color(1) is Color.RED 为 True(可放心用 is 比较)。迭代(按定义顺序):for c in Color。成员判断:Color.RED in Color 为 True、1 in Color 为 False(值不是成员)。当字典键(成员可哈希)。理解「定义继承 Enum、成员作类属性;.name 名/.value 值;C(值)按值、C[‘名’]按名查找;成员唯一(is 比较)、可迭代(按定义顺序)、可当字典键」,就掌握了基本用法。
三、类型安全——纯 Enum 不等于 int/str
理解纯 Enum 的类型隔离:
纯 Enum 的类型安全:成员不等于任何 int/str
class Color(Enum):
RED = 1
Color.RED == 1 # False!(成员 != 它的值)
Color.RED == Color.RED # True(同一成员)
Color.RED.value == 1 # True(要比值用 .value)
→ 纯 Enum 成员是"独立的对象",和它的原始值不相等
→ 这是安全特性:防止枚举和裸数字/字符串混用
好处:
① 传参不会误用别的值
def paint(c: Color): ...
paint(1) # 类型检查器(mypy)会警告
paint(Color.RED) # 正确
② 不同枚举不相等
Color.RED == Size.SMALL # False(即使 value 都是 1)
代价:和需要"原始值"的接口对接麻烦
存数据库/发 JSON 时需要 .value:
db.save(status.value) # 存整数
json.dumps(status.value) # 序列化值
从数据库/JSON 还原时用值查找:
status = Status(db_value)
→ 纯 Enum 不能直接当 int/str 用(要手动 .value)
跨枚举比较:
两个不同 Enum 的成员永远不相等(即使值一样)
→ 这正是"防混用"的价值
所以纯 Enum 成员!=其 value(类型安全防混用),对接原始值接口要手动.value
纯 Enum 的类型安全:成员不等于任何 int/str——Color.RED == 1 为 False(成员 != 它的值)、Color.RED == Color.RED 为 True、Color.RED.value == 1 为 True(要比值用 .value)。纯 Enum 成员是「独立的对象」、和原始值不相等(防止枚举和裸数字/字符串混用)。好处:① 传参不会误用别的值(paint(1) 会被 mypy 警告、paint(Color.RED) 正确)、② 不同枚举不相等(Color.RED == Size.SMALL 为 False 即使 value 都是 1)。代价:和需要「原始值」的接口对接麻烦——存数据库/发 JSON 需要 .value(db.save(status.value))、还原用值查找(Status(db_value))、不能直接当 int/str 用。理解「纯 Enum 成员!=其 value(Color.RED==1 为 False,比值用.value);类型安全好处传参不误用+不同枚举不相等;代价对接原始值接口要手动.value」,就掌握了类型安全。
四、IntEnum、StrEnum、Flag 等变体
理解枚举的各种变体:
IntEnum:成员"同时也是 int"
from enum import IntEnum
class Priority(IntEnum):
LOW = 1
HIGH = 10
Priority.HIGH == 10 # True(IntEnum 和 int 相等!)
Priority.HIGH > Priority.LOW # True(可比较大小)
Priority.LOW + 5 # 6(可参与整数运算)
→ 牺牲一点类型安全,换和 int 的兼容
→ 用于:需要和整数接口/排序/运算对接(如 HTTP 状态码)
StrEnum(Python 3.11+):成员"同时也是 str"
from enum import StrEnum
class Env(StrEnum):
DEV = "dev"
PROD = "prod"
Env.DEV == "dev" # True
Env.DEV.upper() # "DEV"(能用字符串方法)
→ 用于:和字符串接口对接(JSON、配置、URL)
(3.11 前可用 class Env(str, Enum) 达到类似效果)
Flag / IntFlag:位标志(可组合)
from enum import Flag, auto
class Perm(Flag):
READ = auto() # 1
WRITE = auto() # 2
EXEC = auto() # 4
rwx = Perm.READ | Perm.WRITE | Perm.EXEC # 组合
Perm.READ in rwx # True(判断含某标志)
rwx & Perm.WRITE # Perm.WRITE(取交集)
→ 用于:权限、开关组合(一个值表示多个标志)
auto():自动赋值
class X(Enum):
A = auto() # 1
B = auto() # 2
→ 不关心具体值时用,避免手写 1,2,3...
@unique 装饰器:禁止重复值
from enum import unique
@unique
class C(Enum):
A = 1
B = 1 # ✗ ValueError(默认允许别名,@unique 禁止)
所以变体:IntEnum(兼 int)、StrEnum(兼 str,3.11+)、Flag(位标志组合)、auto()自动赋值
枚举的变体:IntEnum(成员同时也是 int)——Priority.HIGH == 10 为 True、可比较大小、可参与整数运算(牺牲一点类型安全换 int 兼容、用于 HTTP 状态码等);StrEnum(3.11+,成员同时也是 str)——Env.DEV == "dev" 为 True、能用字符串方法(用于 JSON/配置/URL、3.11 前用 class Env(str, Enum));Flag/IntFlag(位标志、可组合)——Perm.READ | Perm.WRITE 组合、Perm.READ in rwx 判断、用于权限/开关组合;auto()(自动赋值)——不关心具体值时用;@unique 装饰器(禁止重复值)——默认允许别名、@unique 禁止。理解「变体:IntEnum(兼 int 能比较运算,HTTP 状态码)、StrEnum(兼 str,3.11+,JSON/配置)、Flag/IntFlag(位标志|组合,权限)、auto()自动赋值、@unique 禁止重复值」,就掌握了各种变体。
五、别名、方法与进阶
理解枚举的别名和进阶用法:
别名(同值成员):
class C(Enum):
A = 1
ALIAS_A = 1 # 值和 A 相同 → ALIAS_A 是 A 的"别名"
C.ALIAS_A is C.A # True(别名指向同一成员)
list(C) # 只有 [C.A](别名不出现在迭代中)
→ 允许别名(除非 @unique 禁止)
枚举可以有方法:
class Color(Enum):
RED = 1
GREEN = 2
def is_warm(self): # 实例方法
return self in (Color.RED,)
@classmethod
def from_name(cls, n): # 类方法
return cls[n.upper()]
Color.RED.is_warm() # True
→ 枚举是类,可加方法/属性,封装相关逻辑
自定义值(复杂 value):
class Planet(Enum):
EARTH = (5.976e24, 6.378e6) # value 是元组
def __init__(self, mass, radius):
self.mass = mass # 拆成属性
self.radius = radius
Planet.EARTH.mass # 5.976e24
Functional API(动态创建):
Animal = Enum('Animal', ['DOG', 'CAT', 'BIRD'])
Animal = Enum('Animal', 'DOG CAT BIRD') # 字符串也行
→ 动态生成枚举(少用)
序列化注意:
纯 Enum:存 .value、还原 EnumClass(value)
IntEnum/StrEnum:可直接序列化(本身是 int/str)
→ JSON 常用 StrEnum 或存 .value
所以别名(同值指向同一成员、不参与迭代)、枚举可加方法、value 可为元组拆属性
别名(同值成员):class C(Enum): A = 1; ALIAS_A = 1——ALIAS_A 是 A 的别名(C.ALIAS_A is C.A 为 True、别名不出现在迭代中、允许别名除非 @unique)。枚举可以有方法:def is_warm(self): return self in (Color.RED,)、@classmethod from_name(枚举是类、可加方法/属性封装相关逻辑)。自定义值(复杂 value):class Planet(Enum): EARTH = (5.976e24, 6.378e6) + __init__ 拆成属性(Planet.EARTH.mass)。Functional API(动态创建):Enum('Animal', ['DOG', 'CAT'])(动态生成、少用)。序列化注意:纯 Enum 存 .value 还原 EnumClass(value)、IntEnum/StrEnum 可直接序列化。理解「别名(同值指向同一成员、不参与迭代);枚举可加方法(实例/类方法);value 可为元组配__init__拆属性;序列化纯 Enum 存.value、IntEnum/StrEnum 直接序列化」,就掌握了进阶用法。
六、选型与总结
总结枚举的选型:
选型:用哪种枚举
纯 Enum(默认,最安全):
成员不等于 int/str,类型隔离最强
用于:内部逻辑、状态机、不需和原始值直接混用
代价:对接数据库/JSON 要手动 .value
IntEnum:成员兼是 int
用于:需要和整数比较/排序/运算,或兼容旧整数接口
例:HTTP 状态码、优先级排序
StrEnum(3.11+)/ class X(str, Enum):成员兼是 str
用于:和字符串接口对接(JSON、配置、URL、数据库存字符串)
例:环境名、类型标识
Flag / IntFlag:位标志
用于:可组合的开关/权限(一个值表示多个标志)
auto():不关心具体值时自动赋值
@unique:禁止重复值(防误写别名)
vs 裸常量:
枚举全面优于裸常量(类型安全、可读、防无效、可迭代)
→ 表示"一组有限的命名选项"时都该用枚举
核心总结:
Enum 把命名常量组织成类(name/value、类型安全、成员唯一、可迭代)
纯 Enum 最安全(成员 != int/str,比值用 .value)
IntEnum/StrEnum 换 int/str 兼容
Flag 做位标志、auto() 自动赋值
比裸常量安全可读
所以纯 Enum 最安全、IntEnum/StrEnum 兼容 int/str、Flag 位标志;都比裸常量好
选型:纯 Enum(默认最安全)——成员不等于 int/str、类型隔离最强、用于内部逻辑/状态机(代价对接数据库/JSON 要手动 .value);IntEnum(成员兼是 int)——需要和整数比较/排序/运算或兼容旧整数接口(HTTP 状态码、优先级);StrEnum(3.11+)/class X(str, Enum)(成员兼是 str)——和字符串接口对接(JSON/配置/URL/数据库存字符串);Flag/IntFlag(位标志)——可组合的开关/权限;auto()(自动赋值)、@unique(禁止重复值)。vs 裸常量:枚举全面优于裸常量(表示「一组有限的命名选项」都该用枚举)。理解「纯 Enum 最安全(内部逻辑)、IntEnum(兼 int,状态码/排序)、StrEnum(兼 str,JSON/配置)、Flag(位标志权限);auto()自动/@unique 唯一;都比裸常量好」,就掌握了选型与总结。
记忆钩子:「enum.Enum 是 Python 的『枚举』——把一组有限的命名常量定义成类,每个成员有 name(名字)和 value(值):class Color(Enum):RED=1;GREEN=2,访问 Color.RED(成员)、Color.RED.name(‘RED’)、Color.RED.value(1)、Color(1)按值查找、Color[‘RED’]按名查找;★比裸常量的好处:①类型安全(Color.RED 是独立成员,★纯 Enum 里 Color.RED==1 为 False、不会和裸整数/别的枚举混用,比值用.value)②可读(打印 Color.RED 而非无意义的 1)③成员唯一可 is 比较、可迭代 for c in Color(按定义顺序)、可当字典键④防无效值(Color(5)抛 ValueError);★变体按『要不要和 int/str 兼容』选:纯 Enum 最安全但对接数据库/JSON 要手动.value、IntEnum(成员兼是 int、能比较运算 Priority.HIGH==10 为 True,用于 HTTP 状态码/排序)、StrEnum(3.11+成员兼是 str,3.11 前用 class X(str,Enum),用于 JSON/配置)、Flag/IntFlag(位标志、可|组合,用于权限);auto()自动赋值(1,2,3)、@unique 禁止重复值、别名(同值成员指向同一个、不参与迭代);枚举是类可加方法、value 可为元组配__init__拆成属性」。
七、常见误区与追问
- 误区:纯 Enum 的成员等于它的值,Color.RED == 1。 纯
Enum里是 False——枚举成员是独立的对象、不等于它的原始值,Color.RED == 1为 False,要比较值得用Color.RED.value == 1;这是故意的类型安全设计(防止枚举和裸整数/字符串混用);如果你需要成员「就是」整数(能和 int 相等、比较、运算),要用IntEnum(Priority.HIGH == 10为 True);需要「就是」字符串用StrEnum(3.11+)。 - 误区:1 in Color 能判断 1 是不是合法的枚举值。 不能——
in判断的是「成员」不是「值」,1 in Color为 False(1 是值不是成员),Color.RED in Color才为 True;要判断某个值是否合法,用Color(1)(合法返回成员、非法抛 ValueError)配合 try/except,或1 in [c.value for c in Color],或用Color._value2member_map_(内部映射);注意 Python 3.12+ 对in的行为有调整(可以用值判断),但跨版本安全的做法还是用值查找。 - 误区:枚举定义里两个成员值相同会报错。 默认不报错——值相同的第二个成员会成为第一个的「别名」(
ALIAS_A = 1是A = 1的别名、C.ALIAS_A is C.A为 True、别名不出现在迭代中);如果你想禁止重复值(防止误写),要加@unique装饰器,这样重复值才会抛 ValueError;所以「允许别名」是默认行为、「禁止重复」要显式 @unique。 - 误区:IntEnum 和 Enum 没区别,只是名字不同。 有关键区别——
IntEnum的成员「同时也是 int」:能和整数直接比较相等(Priority.HIGH == 10)、比较大小(HIGH > LOW)、参与算术运算(LOW + 5)、直接序列化成整数;而纯Enum的成员和整数完全隔离(== 1为 False);IntEnum 用「牺牲一点类型安全」换取「和整数接口的兼容性」,适合 HTTP 状态码、需要排序/运算的优先级等;纯 Enum 类型隔离最强、适合不需要和原始值混用的内部逻辑。 - 追问:枚举相比用模块级常量(如 STATUS_ACTIVE = 1)有什么好处? 主要有:① 类型安全——
Status.ACTIVE有明确类型(Status),函数参数标注status: Status后类型检查器能发现误传,而裸常量1可以是任何东西、传错也没人拦;② 防无效值——Status(99)直接抛 ValueError,而process(99)用裸常量时会静默接受无意义的值;③ 可读性——打印/日志里是Status.ACTIVE(自解释)而不是1(一头雾水);④ 归组——一个类装一组相关常量、有明确归属,不像裸常量散落各处;⑤ 防混用——不同枚举的成员永远不相等(即使值相同),而STATUS_ACTIVE=2和PRIORITY_HIGH=2会意外相等;⑥ 附加能力——可迭代(遍历所有合法值)、成员判断、当字典键、可加方法;所以表示「一组有限的命名选项」时应该用枚举。 - 追问:枚举怎么和数据库/JSON 等需要原始值的场景对接? 分情况:① 纯
Enum——存的时候用.value(db.save(status.value)、json.dumps({"status": status.value})),读回来用值查找还原成员(status = Status(db_value)),因为纯 Enum 成员本身不是 int/str、不能直接序列化;② 用IntEnum或StrEnum(或class X(str, Enum))——成员「就是」int/str,可以直接序列化(json.dumps能处理 IntEnum、StrEnum 也能直接当字符串用),读回来时也能直接比较或用值查找;实践中,如果枚举需要频繁和 JSON/数据库/配置文件对接,用 StrEnum(存可读的字符串如 “active”)或 IntEnum(存整数)更省心;如果是纯内部逻辑、追求类型安全,用纯 Enum、序列化时手动.value。 - 追问:Flag 枚举是干什么的,和普通枚举有什么不同?
Flag(和IntFlag)用于「可组合的位标志」——每个成员对应一个二进制位(通常配合auto()得到 1、2、4、8…),可以用位运算|组合多个标志成一个值、用&取交集、用in判断是否包含某标志:比如权限Perm.READ | Perm.WRITE表示同时有读写权限、Perm.READ in perms判断有没有读权限;这和普通枚举(每个成员是互斥的单一选项)不同——普通枚举一个变量只能是一个成员,Flag 一个值能表示多个成员的组合;典型场景是权限系统、功能开关、状态位组合;IntFlag额外让组合值兼容整数(能和 int 做位运算、序列化成整数,兼容 C 风格的位掩码接口)。
八、加强记忆
enum.Enum 是 Python 的「枚举」——把一组有限的命名常量定义成类,每个成员有 name(名字)和 value(值):class Color(Enum): RED = 1; GREEN = 2,访问 Color.RED(成员)、Color.RED.name(‘RED’)、Color.RED.value(1)、Color(1)(按值查找)、Color['RED'](按名查找)。比裸常量的好处:① 类型安全(Color.RED 是独立成员,纯 Enum 里 Color.RED == 1 为 False、不会和裸整数/别的枚举混用,比值用 .value)、② 可读(打印 Color.RED 而非无意义的 1)、③ 成员唯一可 is 比较、可迭代 for c in Color(按定义顺序)、可当字典键、④ 防无效值(Color(5) 抛 ValueError)。变体按「要不要和 int/str 兼容」选:纯 Enum 最安全但对接数据库/JSON 要手动 .value;IntEnum(成员兼是 int、能比较运算、用于 HTTP 状态码/排序);StrEnum(3.11+ 成员兼是 str,3.11 前用 class X(str, Enum)、用于 JSON/配置);Flag/IntFlag(位标志、可 | 组合、用于权限)。auto() 自动赋值、@unique 禁止重复值、别名(同值成员指向同一个、不参与迭代);枚举是类可加方法、value 可为元组配 __init__ 拆成属性。一句话「Enum 把命名常量组织成类(name/value、类型安全、成员唯一、可迭代、防无效值),比裸常量安全可读;纯 Enum 成员!=int/str(比值用.value)、IntEnum/StrEnum 换 int/str 兼容、Flag 做位标志组合、auto()自动赋值」。