当前位置:首页>python>【一起学 Python】第 54 天:Python 3.10+ 新语法:联合类型

【一起学 Python】第 54 天:Python 3.10+ 新语法:联合类型

  • 2026-09-16 19:28:42
【一起学 Python】第 54 天:Python 3.10+ 新语法:联合类型

欢迎来到 Python 学习计划的第 54 天!🎉

昨天我们掌握了基础类型提示(list[int], dict[str, int]),今天我们将继续深入 Python 3.10+ 的新特性,学习一个能让代码更简洁、更易读的语法——联合类型(Union Types)。

这是类型提示进阶的关键一步,学会它,你的代码将更具"现代 Python"风格!

一、什么是联合类型?

联合类型(Union Type)表示一个值可以是多种类型中的任意一种。

在 Python 3.10 之前,我们需要从 typing 模块导入 Union 或 Optional。而 Python 3.10 引入了 PEP 604,允许直接使用 | 运算符来表示联合类型。

1. 核心语法

# Python 3.10+ 语法def process(value: int | str) -> str:    return str(value)# 可以接受 int 或 strprocess(42)       # ✅ OKprocess("hello")  # ✅ OK

2. 新旧语法对比

场景

Python 3.10+ (新)

Python 3.9 及更早 (旧)

联合类型

int | str

Union[int, str]

可选类型

str | None

Optional[str]

多类型联合

int | str | float

Union[int, str, float]

导入需求

无需导入

from typing import Union

# ❌ 旧写法(繁琐)from typing import Union, Optionaldef old_style(value: Union[int, str]) -> str:    return str(value)# ✅ 新写法(简洁)def new_style(value: int | str) -> str:    return str(value)

💡 优势:| 符号直观表达“或”的关系,无需导入 typing 模块,代码更短更清晰。

二、基本用法场景

1. 函数参数

当函数需要接受多种类型的参数时,联合类型非常有用。

def format_value(value: int | float | str) -> str:    """接受整数、浮点数或字符串"""    return f"Value: {value}"format_value(42)        # ✅format_value(3.14)      # ✅format_value("hello")   # ✅

2. 返回值

当函数可能返回不同类型的结果时(例如解析失败返回 None)。

def parse_number(text: str) -> int | float | None:    """尝试解析数字,失败返回 None"""    try:        if "." in text:            return float(text)        return int(text)    except ValueError:        return Noneresult = parse_number("42")     # 返回 intresult = parse_number("3.14")   # 返回 floatresult = parse_number("abc")    # 返回 None

3. 变量注解

变量可以在不同时刻存储不同类型,或者可能为空。

# 变量可以是多种类型user_id: int | str = 123user_id = "ABC123"  # ✅ 也 OK# 可能为 Nonename: str | None = Nonename = "张三"       # ✅ 合法

三、可选类型(Optional)

str | None 等价于 Optional[str],表示值可以是指定类型或 None。这是实际开发中最常见的用法。

# ✅ Python 3.10+ 推荐写法def get_user(user_id: int) -> dict | None:    if user_id == 1:        return {"name": "张三", "age": 25}    return None# 等价于旧写法from typing import Optionaldef get_user_old(user_id: int) -> Optional[dict]:    if user_id == 1:        return {"name": "张三", "age": 25}    return None

四、与集合类型结合

联合类型可以嵌套在列表、字典等容器类型中,描述更复杂的数据结构。

# 列表元素可以是多种类型items: list[int | str] = [1, "two", 3, "four"]# 字典值可以是多种类型config: dict[str, int | str | bool] = {    "name": "MyApp",    "port": 8080,    "debug": True}# 可能返回列表或 Nonedef get_items() -> list[str] | None:    return ["a", "b", "c"]

五、在 isinstance 中使用

Python 3.10+ 允许在 isinstance() 检查中直接使用 | 运算符,无需再写元组。

value = 42# ✅ Python 3.10+if isinstance(value, int | str):    print("是整数或字符串")# 等价于旧写法if isinstance(value, (int, str)):    print("是整数或字符串")

六、实际应用示例

1. 配置解析

配置值的类型往往不固定,联合类型能准确描述这种情况。

def get_config_value(key: str) -> str | int | float | bool | None:    """获取配置值,类型可能不同"""    config = {        "host": "localhost",        "port": 8080,        "timeout": 30.5,        "debug": True    }    return config.get(key)host = get_config_value("host")      # strport = get_config_value("port")      # inttimeout = get_config_value("timeout")# floatmissing = get_config_value("xyz")    # None

2. API 响应处理

API 返回的数据结构可能随接口不同而变化。

def fetch_data(url: str) -> dict | list | None:    """获取 API 数据,可能返回对象、数组或 None"""    if "user" in url:        return {"name": "张三", "age": 25}    elif "users" in url:        return [{"name": "张三"}, {"name": "李四"}]    return Nonedef process_response(data: dict | list | None) -> str:    if data is None:        return "无数据"    elif isinstance(data, dict):        return f"单个对象:{data}"    else:        return f"列表:{len(data)}项"

3. 数据验证

结合类型守卫,我们可以根据传入类型执行不同的验证逻辑。

def validate_input(value: int | str | None) -> tuple[bool, str]:    """验证输入,返回 (是否有效,消息)"""    if value is None:        return False, "值不能为空"    if isinstance(value, int):        if value < 0:            return False, "数值不能为负"        return True, f"有效数值:{value}"    if isinstance(value, str):        if len(value) == 0:            return False, "字符串不能为空"        return True, f"有效字符串:{value}"    return False, "未知类型"

七、类型守卫(Type Guards)

使用条件判断后,类型检查器会自动缩小类型范围,这在处理联合类型时非常重要。

def process(value: int | str | None) -> str:    if value is None:        # 这里 value 的类型被推断为 None        return "空值"    if isinstance(value, int):        # 这里 value 的类型被推断为 int        return f"数字:{value * 2}"    # 这里 value 的类型被推断为 str    return f"字符串:{value.upper()}"

八、版本兼容性写法

如果你的代码需要同时支持 Python 3.9 和 3.10+,有两种方案:

1. 使用 __future__(推荐)

这会推迟注解的求值,允许在 3.7+ 中使用 | 语法。

from __future__ import annotations  # 必须放在文件第一行def process(value: "int | str") -> "str | None":    return str(value)

2. 继续使用 typing 模块

为了最大兼容性(尤其是需要运行时类型检查时),继续使用 Union 和 Optional。

from typing import Union, Optionaldef process(value: Union[int, str]) -> Optional[str]:    return str(value)

九、注意事项与最佳实践

1. 避免过多类型

联合类型过多可能表示设计问题,建议拆分函数。

# ❌ 不推荐:类型过多def process(value: int | str | float | list | dict | tuple | None) -> ...:    pass# ✅ 推荐:使用更具体的类型或重新设计def process_number(value: int | float) -> ...:    passdef process_text(value: str) -> ...:    pass

2. 版本要求

| 语法原生需要 Python 3.10+。旧项目可能需要使用 Union。

3. 嵌套联合

嵌套联合类型会被自动展平。

type1: int | (str | float) = 1  # 等价于 int | str | float

十、总结

知识点

说明

新语法

int | str 替代 Union[int, str]

可选类型

str | None 替代 Optional[str]

优势

无需导入,更简洁直观

Isinstance

3.10+ 支持 isinstance(x, int | str)

兼容性

旧版本需 from __future__ import annotations

建议

避免联合过多类型,保持设计清晰

Python 3.10 引入的 | 运算符是对 typing.Union 的语法糖,让类型提示更简洁易读。类型检查器会根据条件判断自动缩小类型范围(类型守卫)。联合类型适用于多类型参数、可选值、动态返回值等场景。

📌 明日预告:类型别名

明天我们将进入 类型提示模块第四天!

  • 主题:类型别名(Type Aliases)
  • 核心问题:
    1. 如何简化复杂类型(如 dict[str, list[int \| str]])?
    2. TypeAlias 是什么时候引入的?
    3. 类型别名会在运行时创建新类型吗?

💡 提前思考: 如果一个类型签名太长,每次写都很麻烦,该怎么简化?

掌握联合类型新语法,让你的类型提示更现代!继续加油!🚀

最新文章

随机文章