Python 3.10起|可替代Union仅用于类型提示上下文:函数参数、变量/返回值注解、嵌套泛型及Optional等价写法;不可用于isinstance、反射、旧工具链或运行时类型构造。

Python 3.10 起可以直接用 | 替代 Union 做类型标注,但仅限于类型提示上下文,不能用于运行时判断或构造类型对象。
哪些地方能直接用 | 替代 Union
只要是在函数签名、变量注解、返回值标注这类纯类型提示位置,| 就能安全替换 Union:
- 函数参数:
def parse(x: int | str) -> float | None: - 变量声明:
data: dict[str, int | str] = {"a": 1, "b": "ok"} - 嵌套泛型(Python 3.9+ 内置类型):
result: list[int | bool] = [1, True] - 与
Optional等价写法:name: str | None完全等效于Optional[str]
哪些地方不能用 |,必须保留 Union
| 在运行时不是类型构造器,它生成的是 types.UnionType 实例,而传统 Union 是 typing.Union 类型对象——二者不兼容:
-
isinstance(x, int | str)→ 报错:TypeError: isinstance() arg 2 must be a type or tuple of types -
type_union = int | str后传给需要typing.Union实例的工具(如某些旧版mypy插件或自定义类型检查逻辑)会失败 - 需访问
Union.__args__或做反射操作时:(int | str).__args__不存在,而Union[int, str].__args__可用 - 使用
from __future__ import annotations且依赖get_type_hints()的框架(如 FastAPI 0.95 之前)可能无法正确解析|形式
| 和 Union 在静态检查与 IDE 中的行为差异
虽然语义一致,但底层表示不同,会影响工具链行为:
立即学习“Python免费学习笔记(深入)”;
-
mypy默认需显式指定--python-version 3.10才识别|,否则报SyntaxError: invalid syntax - PyCharm 在未正确识别 Python 版本时,输入
int |后可能不触发类型补全(如不提示str) -
get_type_hints(func)返回结果中,int | str通常被标准化为Union[int, str],但具体取决于是否启用from __future__ import annotations和 Python 版本 - 复杂嵌套时可读性下降:
dict[str, list[int | float | str]] | None比Union[dict[str, list[Union[int, float, str]]], None]更紧凑,但括号和层级容易混乱
真正容易被忽略的是:你写的 | 标注在运行时根本“不存在”——它不会影响程序执行,只服务于类型检查器和 IDE。一旦涉及反射、动态类型构造或跨版本兼容,就得切回 Union,不能凭直觉认为“写法一样,行为就一样”。


















