第 25 课 · 进阶 · 19 分钟

Python 类型提示

让读者和工具一眼看出数据的形状。

类型提示函数注解list[int]可选返回值

新来的店员看着订单字典,猜「qty」是什么意思。类型标注在代码跑起来之前就说明它是整数。可 Python 在运行时真的会管吗?

类型提示是可选的注解,用来说明函数接收和返回什么样的值。Python 运行时不会强制执行这些提示,但编辑器、检查工具和同事可以借此在运行前发现错误。 你还会描述回调、类 JSON 记录,以及输入与输出类型之间的关系。

给函数加注解

参数后面的冒号写出预期类型,箭头写出返回类型。提示会保存在 __annotations__ 中,但不会转换值。传入非字符串仍然会运行,直到代码本身出错。

def greet(name: str) -> str:
    return f"Hello, {name}"
print(greet("Ada"))

参数与返回类型

描述集合

list[int] 表示每个元素都是 int。现代 Python 支持内置泛型,读起来也很直接。提示描述的是接口,不会在函数调用时逐个检查元素。

def total(values: list[int]) -> int:
    return sum(values)
print(total([1, 2, 3]))

带类型的列表

说明值可能不存在

键不存在时,dict.get 返回 None,所以返回类型也应包含 None。联合类型写法 float | None 直接表达这种可能。调用方可以先处理缺失情况,再做算术。

def find_price(prices: dict[str, float], item: str) -> float | None:
    return prices.get(item)
print(find_price({"tea": 3.5}, "tea"))
print(find_price({"tea": 3.5}, "coffee"))

可能有值,也可能是 None

Callable 与 Iterable 描述行为

类型提示不只描述内置类型,也能描述函数接受什么。Callable[[int], int] 表示参数是从 int 到 int 的函数;Iterable[int] 接受列表、生成器和其他流。提示帮助编辑器,不改变运行时行为。

from collections.abc import Callable, Iterable

def apply_all(values: Iterable[int], operation: Callable[[int], int]) -> list[int]:
    return [operation(value) for value in values]

print(apply_all([1, 2, 3], lambda n: n * 2))

连回调一起注解

TypedDict 描述记录形状

TypedDict 给字典的键和值类型起名字,适合 JSON 边界。运行时它仍然是普通 dict,不会自动检查键或类型。解码后仍要单独校验数据,再信任它。

from typing import TypedDict

class Order(TypedDict):
    drink: str
    price: float
    quantity: int

order: Order = {"drink": "latte", "price": 4.5, "quantity": 2}
print(order["drink"], order["price"] * order["quantity"])

给键起名,不改变运行时

TypeVar 保持输入输出关系

TypeVar 表示同一个类型在函数中流动。first(list[int]) 返回 int | None,first(list[str]) 返回 str | None。没有类型变量,最多只能说返回 object,调用方会丢失有用信息。

from typing import TypeVar
T = TypeVar("T")

def first(items: list[T]) -> T | None:
    return items[0] if items else None

print(first([1, 2, 3]))
print(first(["latte"]))
print(first([]))

把元素类型带到返回值

本课要点

  • 参数提示写在冒号后,返回提示写在 -> 后。
  • list[int] 和 dict[str, float] 描述集合里的内容。
  • float | None 表示值可能缺失。
  • 类型提示是文档和工具输入,不是运行时强制检查。
  • 提示描述接口;TypedDict 和 TypeVar 补充形状与关系,不做运行时检查。

常见错误

  • 以为违反类型提示时 Python 会自动抛出 TypeError。
  • 只在注释里写 list[int],却没有写进函数签名。
  • 查找可能失败时,返回类型忘记包含 None。
  • 以为违反注解本身就会抛出 TypeError。
轮到你

给 double(n: int) -> int 加注解并打印 double(4),再给一个返回 str | None 的函数加注解。

动手试试

改改变量、先预测输出,再运行代码。第一次点击“运行代码”时会下载 Python 运行时,可能需要几秒钟。

浏览器内 Python本地运行 · 无需账号
首次运行会从 CDN 下载 Pyodide。修改后点击“运行代码”。

练习本课

12 道题,作答后立即看到解释。

查看 12 道题答案开始练习
← assert 测试生成器 →