enum严格区分name(标识符)和value(任意对象),str(e)显示name而非value;序列化需处理value;避免继承str/int,改用@property;intenum/flag重载运算符,非语法糖;反查枚举优先用构造函数或try/except。

Enum 成员值不是字符串时,name 和 value 容易混淆
很多人以为 Enum 成员的“名字”就是它打印出来的东西,结果在序列化或日志里拿到一串数字或对象,傻眼了。根本原因是:Python 的 Enum 严格区分 name(定义时的标识符)和 value(赋给它的任意 Python 对象)。
-
Color.RED的name是"RED",value是1;如果写成RED = "red",那value就是字符串"red" - 用
str(e)或直接 print,显示的是name(如Color.RED→"Color.RED"),不是value - 想取可读字符串?优先用
e.name.lower()或e.value,别依赖str(e) - 常见错误:
json.dumps([Color.RED])报TypeError: Object of type Color is not JSON serializable—— 因为没处理value
需要带方法或属性的枚举?用 Enum + @property,别继承 int 或 str
有人为了加个描述字段,强行让枚举继承 str,结果所有成员都变成字符串类型,丢失了枚举语义,也破坏了类型检查。正确做法是保持纯 Enum,用 @property 暴露计算字段。
- 错误示范:
class Status(str, Enum): PENDING = "pending"→isinstance(Status.PENDING, str)是True,但Status.PENDING == "pending"也会意外成立,容易引发逻辑 bug - 正确写法:定义普通
Enum,在类内加@property方法返回描述、颜色、HTTP 状态码等 - 示例:
class HttpStatus(Enum): OK = 200 NOT_FOUND = 404 @property def description(self): return {200: "OK", 404: "Not Found"}.get(self.value, "") - 这样既保留类型安全,又支持 IDE 补全和 mypy 检查,
HttpStatus.OK.description也能正常调用
IntEnum 和 Flag 不是语法糖,它们改变比较行为和位运算能力
看到 IntEnum 能跟整数比较就用,看到 Flag 有 | 就硬套,结果发现行为不符合预期——这两者底层重载了 ==、&、| 等操作符,不是简单“带整数值的枚举”。
-
IntEnum成员和整数==返回True(HttpStatus.OK == 200成立),但普通Enum不会;这在接口兼容旧代码时有用,但也埋下隐式类型转换隐患 -
Flag支持位组合,但必须显式用|构造,不能直接赋值READ | WRITE(会报错);正确方式是class Perm(Flag): READ = 1; WRITE = 2,再用Perm.READ | Perm.WRITE - 误用
Flag当普通枚举:如果值不是 2 的幂(比如READ = 1; EXEC = 3),EXEC in (READ | EXEC)会返回False,因为底层按位判断 - 性能影响小,但类型系统里
IntEnum会被当成int,mypy 可能漏掉本该报错的枚举误用
从字符串或数字反查枚举成员?优先用 try/except KeyError,别用 getattr 或 dict.get
用户输入、API 返回的字符串要转成枚举,很多人习惯用 getattr(MyEnum, s, None) 或 MyEnum.__members__.get(s),结果遇到大小写不一致、空格、下划线命名差异就挂掉。
立即学习“Python免费学习笔记(深入)”;
-
getattr查的是name,不是value;如果枚举用的是RED = "#ff0000",那getattr(Color, "#ff0000")一定失败 - 推荐统一走构造函数:
Color(s)(查value)、Color[s](查name)、Color(s, strict=False)(3.11+ 的宽松模式) - 最稳写法:
try: status = HttpStatus(int(raw_input)) except (ValueError, KeyError): status = HttpStatus.NOT_FOUND - 注意:用
Color[s]时,s必须完全匹配定义时的name(大小写、下划线),没有自动 normalize









