新来的店员看着订单字典,猜「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 运行时,可能需要几秒钟。
练习本课
12 道题,作答后立即看到解释。