Skip to content

Python 类型注解

本文介绍 Python 的类型注解(Type Hints):语法、typing 模块、静态检查工具 mypy,以及实践建议。

作者:yanshaodong

为什么使用类型注解

  • 可读性:显式声明接口契约,降低理解成本。
  • 工具支持:IDE 自动补全、静态检查在运行前发现错误。
  • 可维护性:重构时由类型检查器保障一致性。

类型注解默认不参与运行时(除非用 typing.get_type_hintspydantic),需借助静态检查器生效。

基础注解

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

实践建议

  1. 在**公共 API(函数签名、类属性)**上优先加注解。
  2. 内部逻辑可渐进式补充,不必一次到位。
  3. 配合 mypy --strictpyright 在 CI 中强制检查。
  4. 运行时校验用 pydantic(如 FastAPI 的请求体模型)。

小结

  • 类型注解提升可读性与工具智能,不影响运行。
  • 优先用内建泛型(list[int])而非 typing.List
  • Optional / Union / Callable 覆盖多数场景。
  • 静态检查用 mypy/pyright,运行时校验用 pydantic。