python 3.10起union被|运算符正式替代,int | str等价于union[int, str]但更简洁、无需导入、生成uniontype实例,且union已弃用。

Python 3.10 中 Union 已被 | 运算符替代
Python 3.10 开始原生支持类型联合的中缀语法,Union[int, str] 可直接写成 int | str。这是 PEP 604 引入的正式特性,不是语法糖,而是类型系统一级支持——int | str 在运行时就是 types.UnionType 实例,而不再是 typing.Union 的泛型对象。
实际使用时,只要确保 Python 版本 ≥ 3.10,就应优先用 |;继续用 Union 不报错但属于过时写法,且在某些静态检查器(如 mypy 1.0+)中可能触发警告。
-
def parse_value(x: int | str) -> float | None:✅ 推荐 -
def parse_value(x: Union[int, str]) -> Union[float, None]:❌ 不必要,且Union[float, None]应写作float | None - 函数注解、变量注解、类型别名中均可直接使用
|
嵌套联合类型与括号的必要性
| 是左结合、低优先级运算符,遇到复杂结构必须加括号,否则解析会出错或含义不符。
例如:list[int] | dict[str, int] 没问题,但 list[int | str] 和 list[int] | str 完全不同——前者是「元素为 int 或 str 的列表」,后者是「int 列表 或 str」。
-
Optional[list[int | str]]→ 错误:Optional是type | None的简写,这里应写list[int | str] | None -
dict[str, int | float] | None✅ 含义清晰 -
dict[str, (int | float)] | None✅ 括号不强制,但增强可读性 -
Callable[[int | str], bool]✅ 参数类型联合写在内层
与 typing.Union 兼容性及运行时行为差异
虽然语法上推荐 |,但 typing.Union 在 3.10+ 仍可用,且二者在大多数静态检查场景下等价。不过关键区别在于运行时:
-
int | str的类型对象是types.UnionType,而Union[int, str]返回的是typing.Union泛型实例(类型为typing._GenericAlias) -
isinstance(x, int | str)会报TypeError:不能对UnionType实例做isinstance检查;而isinstance(x, Union[int, str])也不合法(Union不是类) - 真正需要运行时类型判断时,得用
isinstance(x, (int, str))—— 注意这里是元组,不是联合类型 - 第三方库(如 Pydantic v2、FastAPI)内部已适配
|,但若你手动调用get_origin()/get_args(),需同时处理UnionType和_GenericAlias
IDE 和 linter 常见误报与应对
部分旧版 IDE 插件(如 PyCharm 2022.2 之前)或 linter(如 pyright 旧配置)可能将 | 报为语法错误,或无法正确推导联合类型的成员。这不是代码问题,而是工具链未更新。
- 确认 Python 解释器版本为 3.10+,并在
pyproject.toml或setup.py中声明requires-python = ">=3.10" - PyCharm:设置 → Project → Python Interpreter → 确保选中 3.10+;并启用 “PEP 604 syntax support”(通常默认开启)
- pyright:升级到 1.1.280+,并在
pyrightconfig.json中确保"pythonVersion": "3.10" - mypy:需 0.930+,且命令行加
--python-version 3.10或配置[mypy] python_version = "3.10"
联合类型本身不增加运行时开销,但过度嵌套(如 A | B | C | D | ... 超过 10 项)可能拖慢类型检查器,这时建议提取为类型别名。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











