Python 3.10起int | str是合法类型注解,等价于Union[int, str],但本质是PEP 604引入的底层变更:无需导入、生成UnionType实例、嵌套更简洁,且Union已弃用。

Python 3.10 起,int | str 就是合法的类型注解,它和 Union[int, str] 完全等价,但不需要导入、更短、更贴近自然语言逻辑——这不是语法糖,而是 PEP 604 正式引入的底层类型系统变更。
Union[int, str] 和 int | str 的实际差异在哪
表面上只是写法变短,但背后有三处关键区别:
-
Union是一个泛型类,需要从typing模块导入;|是运算符,直接作用于类型对象,无需任何导入 - 运行时行为不同:
int | str在 Python 3.10+ 中生成的是types.UnionType实例,而Union[int, str]生成的是typing.Union类型(在 3.10+ 中已被标记为弃用警告) - 嵌套表达更清晰:比如
list[int | str]比list[Union[int, str]]少两层括号,也避免和函数调用混淆
什么时候会触发 DeprecationWarning
如果你还在用 Union,且项目已升级到 Python 3.10+,静态检查工具(如 mypy)或运行时(启用 -W default)可能不会报错,但以下情况会明确提示:
- 显式使用
from typing import Union后又没实际用到它(mypy 可能报 unused-import) - 在类型别名中写
MyType = Union[int, str],而代码中其他地方都用|—— 工具链可能认为风格不一致 - 某些 IDE(如 VS Code + Pylance)会在 hover 提示里标注 “
Unionis deprecated in favor of|”
Optional[str] 还能不能用 | 替代
可以,但不推荐直接写 str | None 来代替 Optional[str],原因很实际:
立即学习“Python免费学习笔记(深入)”;
-
Optional[T]是Union[T, None]的别名,语义上强调“可选性”,而T | None更偏向“类型并集”——阅读者第一反应不同 - 大多数类型检查器对
Optional有特殊处理(比如自动推导默认值为None),T | None有时会丢失这部分上下文 - 框架如 FastAPI、Pydantic 仍优先识别
Optional作为字段可空标志,T | None虽然也能工作,但文档生成或错误提示可能不够精准
真实项目里最容易忽略的兼容性坑
不是语法写错,而是环境和工具链没跟上:
- 旧版 mypy(int | str,会直接报
SyntaxError—— 升级 mypy 到 0.930+ 是硬要求 - CI 流水线如果还跑在 Python 3.9 或更早版本,
|写法会直接让整个 type check 阶段失败,连语法解析都过不去 - 团队协作时,有人用 3.10+ 写了
dict[str, int | float],另一人用 3.9 打开就 SyntaxError —— 不是代码问题,是解释器版本卡死
真正要落地 | 写法,得先确认 Python 版本、mypy 版本、IDE 插件支持度这三者都对齐。否则,简洁性反而成了协作障碍。


















