主题
Python 类型注解
本文介绍 Python 的类型注解(Type Hints):语法、typing 模块、静态检查工具 mypy,以及实践建议。
作者:yanshaodong
为什么使用类型注解
- 可读性:显式声明接口契约,降低理解成本。
- 工具支持:IDE 自动补全、静态检查在运行前发现错误。
- 可维护性:重构时由类型检查器保障一致性。
类型注解默认不参与运行时(除非用
typing.get_type_hints或pydantic),需借助静态检查器生效。
基础注解
python
name: str = "Alice"
age: int = 18
height: float = 1.75
active: bool = True函数签名:
python
def add(a: int, b: int) -> int:
return a + b
def greet(name: str) -> str:
return f"Hello, {name}"容器类型
python
from typing import List, Dict, Set, Tuple
nums: List[int] = [1, 2, 3]
scores: Dict[str, float] = {"a": 90.5}
tags: Set[str] = {"x", "y"}
point: Tuple[int, int] = (3, 4)Python 3.9+ 可直接用内建泛型:
python
nums: list[int] = [1, 2, 3]
scores: dict[str, float] = {"a": 90.5}
point: tuple[int, int] = (3, 4)typing 常用工具
python
from typing import Optional, Union, Any, Callable, Iterable
def find(uid: int) -> Optional[str]:
# 可能返回 None
...
def parse(v: Union[str, bytes]) -> str:
...
def handle(fn: Callable[[int], int]) -> None:
...
def total(xs: Iterable[int]) -> int:
return sum(xs)Optional[X] 等价于 Union[X, None]。
自定义类型与别名
python
from typing import NewType, TypeAlias
UserId = NewType("UserId", int)
def get_user(uid: UserId) -> str:
return f"user-{uid}"
Vector: TypeAlias = list[float]泛型与 Protocol
python
from typing import TypeVar, Generic
T = TypeVar("T")
class Stack(Generic[T]):
def __init__(self) -> None:
self._items: list[T] = []
def push(self, item: T) -> None:
self._items.append(item)
# 结构化子类型(鸭子类型静态化)
from typing import Protocol
class Sized(Protocol):
def __len__(self) -> int: ...
def size(obj: Sized) -> int:
return len(obj)静态检查 mypy
安装:
bash
pip install mypy检查:
bash
mypy your_module.py示例(mypy 会报错):
python
def add(a: int, b: int) -> int:
return a + b
add("x", "y") # error: Argument 1 to "add" has incompatible type "str"pyproject.toml 配置:
toml
[tool.mypy]
python_version = "3.10"
strict = true
ignore_missing_imports = true实践建议
- 在**公共 API(函数签名、类属性)**上优先加注解。
- 内部逻辑可渐进式补充,不必一次到位。
- 配合
mypy --strict或pyright在 CI 中强制检查。 - 运行时校验用
pydantic(如 FastAPI 的请求体模型)。
小结
- 类型注解提升可读性与工具智能,不影响运行。
- 优先用内建泛型(
list[int])而非typing.List。 Optional/Union/Callable覆盖多数场景。- 静态检查用 mypy/pyright,运行时校验用 pydantic。