类型注解与工程规范
类型注解是 Python 工程的标配(大项目必用),工程规范决定协作质量。面试主线:typing 怎么用、工程怎么搭(虚拟环境、包管理、工具链)。
类型注解基础
def fetch(user_id: int, tag: str | None = None) -> dict[str, str]:
...- 运行时不强制,注解是给类型检查器(mypy/pyright)和 IDE 用的
str | None(3.10+)等价于Optional[str]
typing 常用工具
| 工具 | 用途 |
|---|---|
Optional[X] |
X 或 None |
Union[A, B] / A | B |
联合类型 |
list[str] / dict[str, int] |
泛型容器(3.9+ 直接用小写) |
TypeVar |
泛型变量(函数内类型关联) |
Protocol |
结构化类型(鸭子类型标注,见设计模式篇) |
TypedDict |
dict 的键类型约束 |
Literal["a", "b"] |
字面量取值限制 |
Callable[[int], str] |
函数类型 |
from typing import TypeVar
T = TypeVar("T")
def first(items: list[T]) -> T: # 输入输出类型关联
return items[0]
first([1, 2]) # 推断返回 int
first(["a"]) # 推断返回 strPEP8 与代码规范
| 维度 | 规范 |
|---|---|
| 命名 | 类 PascalCase、函数/变量 snake_case、常量 UPPER |
| 行宽 | 79/88 字符(black 默认 88) |
| import | 标准库、第三方、本地三组,每组按字母序 |
| 空格 | 运算符两侧、逗号后 |
| 类型 | 公共 API 必须注解 |
工具链:black(格式化)、ruff(lint + 格式化,替代 flake8/isort)、mypy/pyright(类型检查)。现代项目用 ruff 一把梭。
虚拟环境
虚拟环境隔离依赖,避免全局污染:
python -m venv .venv # 标准库方案
source .venv/bin/activate # Windows: .venv\Scripts\activate
uv venv # uv 方案, 更快包管理:pip 与 uv
| 维度 | pip | uv |
|---|---|---|
| 定位 | 标准包管理器 | 新一代全能工具(Rust 实现,快 10-100 倍) |
| 虚拟环境 | 需 venv 配合 | 内置 |
| 依赖锁 | requirements.txt 手工 | uv.lock 自动生成 |
| 项目配置 | setup.py/setuptools | pyproject.toml |
pyproject.toml 是现代的工程配置中心(PEP 621):项目元数据、依赖、构建工具、ruff/black 配置全在里面。
uv init myapp && cd myapp
uv add fastapi uvicorn # 装依赖并写进 pyproject
uv run uvicorn main:app # 在虚拟环境里跑面试追问
- 类型注解是强制的吗? 运行时不是(Python 动态类型),但类型检查器在 CI 强制。大项目标配
- TypeVar 干什么? 泛型类型变量,让函数输入输出类型关联。first(list[T]) -> T
- Protocol 和 ABC 的区别? Protocol 结构匹配不强制继承(鸭子类型标注),ABC 显式继承。见设计模式篇
- uv 比 pip 强在哪? Rust 实现快一个数量级,内置虚拟环境和锁文件,pyproject.toml 一体化
- 工程规范工具链? ruff(lint+格式)、black(格式)、mypy/pyright(类型)、uv(包管理+环境)