Python 类型注解是渐进式类型系统:运行时不做任何校验,价值全在 mypy/pyright 静态检查与 IDE 提示。
基本注解
# 变量
count: int = 0
ratios: list[float] = []
# 函数签名
def scale(data: list[float], k: float = 1.0) -> list[float]:
return [x * k for x in data]PEP 604 起 X | Y 取代 Union[X, Y],可空类型写 X | None(取代 Optional[X]):
def find(name: str) -> dict[str, int] | None: ...
# Python 3.9 及以下的等价写法
from typing import Optional
def find(name: str) -> Optional[dict[str, int]]: ...容器泛型
3.9+ 直接用内建容器作泛型,不再需要 typing.List:
from typing import Any
matrix: list[list[float]] = []
cache: dict[str, Any] = {}
ids: tuple[int, ...] = (1, 2, 3) # 定长 tuple[int, str],变长用 ...泛型函数:TypeVar
from typing import TypeVar
T = TypeVar("T")
def first(seq: list[T]) -> T: # 输出类型与输入元素类型绑定
return seq[0]TypeVar 让检查器追踪「输入输出类型相同」这类约束;TypeVar("N", bound=float) 可设上界,多个具体 TypeVar 可表达协变关系。
Callable / TypedDict / Literal
from typing import Callable, TypedDict, Literal
# 可调用对象:参数类型 + 返回类型
handler: Callable[[str, int], bool]
# 键与值类型都受限的字典
class Point(TypedDict):
x: float
y: float
# 只允许字面取值,适合模式/开关类参数
Mode = Literal["train", "eval", "predict"]
def run(mode: Mode) -> None: ...
run("train") # OK
run("fit") # mypy 报错Protocol:结构化类型
协议与抽象基类 走显式继承做 nominal typing;Protocol 只看结构有没有那个方法——鸭子类型的静态化:
from typing import Protocol
class Closeable(Protocol):
def close(self) -> None: ...
def shutdown(res: Closeable) -> None: # 任何有 close() 的对象都匹配
res.close()运行时不校验
注解只是元数据,存于 __annotations__,解释器不检查:
def add(a: int, b: int) -> int:
return a + b
add("1", "2") # 照样运行,返回 "12"需要运行时强制校验用 Pydantic;注解配合 数据类 dataclass 则能消除手写 __init__ 的样板。
from future import annotations
模块顶部加这一行后,所有注解延迟求值、以字符串存储(PEP 563),前向引用不再需要引号:
from __future__ import annotations
class Node:
def next(self) -> Node | None: ... # Node 未定义完即可引用mypy、pyright 才是注解的真正消费者:本地 IDE 实时检查,CI 里接入静态检查即获得接近静态语言的类型安全。