视频加载失败

Python StrEnum 与 Literal 的区别

407 字
2 分钟
Python StrEnum 与 Literal 的区别

StrEnum 和 Literal 虽然都能限制字符串取值,但用途完全不同。

1. StrEnum:运行时的枚举类型#

Python 3.11+

from enum import StrEnum
class Status(StrEnum):
PENDING = "pending"
SUCCESS = "success"
FAILED = "failed"

使用:

status = Status.PENDING
print(status) # pending
print(status.value) # pending

特点:

  • 运行时真实存在的对象
  • 可以遍历
  • 可以比较
  • 可以作为配置、数据库字段、API参数等统一定义
for s in Status:
print(s)
if status == Status.PENDING:
...

2. Literal:类型提示#

来自 typing

from typing import Literal
Status = Literal[
"pending",
"success",
"failed"
]

使用:

def update_status(
status: Status
):
...

IDE 会提示:

update_status("pending") # ✅
update_status("abc") # ❌ 类型检查报错

特点:

  • 只存在于类型系统
  • 运行时没有枚举对象
  • 不能遍历
  • 不能写 Status.PENDING
print(Status)

输出:

typing.Literal['pending', 'success', 'failed']

对比#

特性StrEnumLiteral
运行时存在✅❌
类型检查✅✅
可遍历✅❌
可作为常量✅❌
IDE 自动补全✅一般
JSON/API 参数约束✅✅
数据库存储映射✅❌

FastAPI/Pydantic 场景#

通常推荐:

from enum import StrEnum
class ModelProvider(StrEnum):
OPENAI = "openai"
ANTHROPIC = "anthropic"
GEMINI = "gemini"
from pydantic import BaseModel
class Request(BaseModel):
provider: ModelProvider

自动生成 OpenAPI:

{
"enum": [
"openai",
"anthropic",
"gemini"
]
}

同时还能:

if req.provider == ModelProvider.OPENAI:
...

什么时候用 Literal?#

当你只是想约束几个字符串参数,而且不会在别处复用:

def create_message(
role: Literal[
"user",
"assistant",
"system"
]
):
...

这种场景用 Literal 很轻量。


实际项目建议#

  • 业务领域概念(状态、模型提供商、订单类型等) → StrEnum
  • 函数参数的简单约束 → Literal
  • FastAPI/Pydantic Schema → 优先 StrEnum

很多大型 Python 项目(如 Pydantic、FastAPI、LangGraph 等)最终都会把重要的字符串常量抽成 StrEnum,因为它既有类型安全,又有运行时能力。

文章分享

如果这篇文章对你有帮助,欢迎分享给更多人!

Python StrEnum 与 Literal 的区别
https://blog.81vm3.xyz/posts/python-strenum-literal/
作者
Blume
发布于
2025-09-10
许可协议
CC BY-NC-SA 4.0
Profile Image of the Author
Blume
I build interesting things.
公告
欢迎来到我的博客!
分类
标签
最新动态
站点统计
文章
38
分类
5
标签
98
总字数
23,078
运行时长
0 天
最后活动
0 天前
站点信息
构建平台
Local
博客版本
Firefly v6.16.8
文章许可
CC BY-NC-SA 4.0
文章目录