python 3.10起|可直接替代union,如int | str等价于union[int, str],无需导入、更简洁,是pep 604正式特性;但仅限类型标注,不适用于isinstance等运行时场景。

Python 3.10 的 | 联合类型语法可以直接替代 Union
Python 3.10 正式支持用 | 作为类型联合操作符,比如 int | str 等价于 Union[int, str],且无需从 typing 导入 Union。这是 PEP 604 引入的特性,已成标准用法。
但要注意:这种写法只在 Python 3.10+ 运行时有效;若需兼容旧版本(如 3.9 或更早),仍得用 Union,否则会报 SyntaxError: invalid syntax。
-
|只能用于类型提示上下文(函数签名、变量注解等),不能用于运行时表达式,比如x = int | str会抛NameError - 嵌套联合要加括号:写成
int | str | None没问题,但list[int] | dict[str, int]必须写为list[int] | dict[str, int](无需额外括号);而Optional[int | str]是非法的,应写成int | str | None - 与泛型组合时注意优先级:
list[int | str]合法,list[int] | str表示“列表或字符串”,不是“元素为 int 或 str 的列表”
函数参数和返回值中怎么安全地用 | 写联合类型
直接替换旧写法即可,但需留意类型检查器(如 mypy、pyright)是否启用 PEP 604 支持——多数现代工具默认开启,但某些老配置可能禁用。
示例:
def parse_value(s: str) -> int | float | None:
try:
return int(s)
except ValueError:
try:
return float(s)
except ValueError:
return None
- 返回类型
int | float | None比Union[int, float, None]更紧凑,语义更接近自然语言中的“或” - 如果函数实际返回了未声明的类型(比如
bool),mypy 会报错:Returning incompatible type "bool"; expected "int | float | None" - 运行时该注解不生效,不会做自动类型转换或校验,纯属静态检查契约
类属性和变量注解里用 | 时容易忽略的细节
变量注解中使用 | 和函数注解规则一致,但常见疏漏在于模块级常量或数据类字段。
- 数据类中字段类型必须显式标注,
field: int | str合法;但若用了default_factory,返回值类型仍需匹配该联合类型,否则 mypy 可能误报 - 模块级变量如
CONFIG_PATH: str | None = os.getenv("CONFIG")是推荐写法;但若该变量后续被赋值为Path对象,而类型注解没包含Path,就会触发类型不匹配警告 - 注意
None在联合中的位置无关紧要:str | None和None | str完全等价,但前者是惯例写法
与 Optional、Union 混用时的兼容性陷阱
Optional[T] 在 3.10+ 中仍是合法的,但它只是 T | None 的别名;两者可混用,但不应同时出现在同一代码库中,否则会降低一致性。
- 不要写
Optional[int | str]—— 这是语法错误,因为Optional只接受单个类型参数;正确写法是int | str | None - 若项目需支持 Python Union,并避免
|;迁移到 3.10 后可批量替换,但要注意第三方库的类型存根是否已适配(比如某些旧版typeshed可能尚未更新|语法) - 使用
from __future__ import annotations可缓解部分前向引用问题,但它不影响|语法本身的支持——该语法由解析器层面实现,不依赖延迟注解
真正麻烦的是跨版本 CI 场景:同一个代码库既要跑 mypy on 3.9 又要跑 on 3.10,此时 | 语法会直接让 3.9 解析失败。这种情况下只能暂缓升级或切分类型检查环境。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











