类型检查工具
类型注解本身不影响 Python 运行时行为。类型检查工具(mypy、pyright)在运行前发现类型错误。
mypy:标准类型检查器
安装和基本使用
bash
pip install mypy
# 检查单个文件
mypy script.py
# 检查整个目录
mypy src/
# 显示更多信息
mypy --show-error-codes script.py示例
代码(example.py):
python
def add(a: int, b: int) -> int:
return a + b
result = add(5, 10)
print(result)
# 类型错误
result = add("5", "10")运行 mypy:
bash
$ mypy example.py
example.py:7: error: Argument 1 to "add" has incompatible type "str"; expected "int"
example.py:7: error: Argument 2 to "add" has incompatible type "str"; expected "int"
Found 2 errors in 1 file (checked 1 source file)配置文件
创建 mypy.ini 或 pyproject.toml:
mypy.ini:
ini
[mypy]
python_version = 3.12
warn_return_any = True
warn_unused_configs = True
disallow_untyped_defs = True
[mypy-tests.*]
disallow_untyped_defs = Falsepyproject.toml:
toml
[tool.mypy]
python_version = "3.12"
warn_return_any = true
warn_unused_configs = true
disallow_untyped_defs = true
[[tool.mypy.overrides]]
module = "tests.*"
disallow_untyped_defs = false常用配置
| 选项 | 说明 |
|---|---|
disallow_untyped_defs | 禁止无类型注解的函数 |
disallow_any_generics | 禁止 list 而非 list[int] |
warn_redundant_casts | 警告多余的类型转换 |
warn_unused_ignores | 警告多余的 # type: ignore |
strict | 启用所有严格检查 |
pyright/pylance
微软开发的高性能类型检查器,集成在 VS Code 的 Pylance 扩展中。
安装
bash
npm install -g pyright
# 或使用 pipx
pipx install pyright使用
bash
pyright script.py
pyright src/配置
创建 pyrightconfig.json:
json
{
"pythonVersion": "3.12",
"typeCheckingMode": "strict",
"reportMissingTypeStubs": false,
"exclude": [
"**/node_modules",
"**/__pycache__"
]
}渐进类型(Gradual Typing)
无需一次性为所有代码添加类型:
阶段 1:关键接口
python
# 只为公共 API 添加类型
def process_data(data: list[dict]) -> dict:
# 内部实现无类型
result = {}
for item in data:
key = item["id"]
result[key] = item
return result阶段 2:关键路径
python
def process_data(data: list[dict[str, any]]) -> dict[int, dict]:
result: dict[int, dict] = {}
for item in data:
key: int = item["id"]
result[key] = item
return result阶段 3:完整类型
python
from typing import TypedDict
class Item(TypedDict):
id: int
name: str
def process_data(data: list[Item]) -> dict[int, Item]:
result: dict[int, Item] = {}
for item in data:
result[item["id"]] = item
return resultAny:动态类型逃生舱
Any 关闭类型检查,用于处理真正动态的数据:
python
from typing import Any
import json
def load_config(path: str) -> Any:
with open(path) as f:
return json.load(f) # JSON 可以是任何结构
config = load_config("config.json")
config.database.host # 类型检查器不报错限制 Any 的传播:
python
from typing import Any, cast
def load_config(path: str) -> dict[str, Any]:
with open(path) as f:
data = json.load(f)
return cast(dict[str, Any], data) # 明确类型类型忽略
单行忽略
python
result = some_function() # type: ignore
# 指定错误码
result = some_function() # type: ignore[arg-type]文件级忽略
python
# mypy: ignore-errors
# 整个文件不检查
def untyped_function(x, y):
return x + y何时使用
- 与无类型第三方库交互
- 已知的类型系统限制
- 临时绕过(应添加 TODO 注释)
不要滥用:过度使用会失去类型检查的好处。
第三方库类型存根
typeshed
Python 标准库和常用第三方库的类型存根:
bash
# 大多数库已包含类型信息
pip install requests # 自带类型
# 部分老库需要单独安装类型存根
pip install types-requests为无类型库创建存根
项目结构:
my_project/
├── src/
│ └── main.py
└── stubs/
└── untyped_lib/
└── __init__.pyi存根文件(__init__.pyi):
python
def some_function(x: int, y: str) -> bool: ...
class SomeClass:
def method(self) -> None: ...mypy 配置:
ini
[mypy]
mypy_path = stubs常见类型错误
错误 1:incompatible type
python
def add(a: int, b: int) -> int:
return a + b
add("5", "10") # error: Argument 1 has incompatible type "str"; expected "int"修复:传入正确类型或修改签名。
错误 2:missing return
python
def divide(a: int, b: int) -> int:
if b != 0:
return a // b
# error: Missing return statement修复:处理所有路径。
错误 3:untyped function
python
# error: Function is missing a type annotation
def process(data):
return data * 2修复:添加类型注解或在配置中放宽限制。
实战:为已有项目添加类型
步骤 1:生成存根
bash
stubgen -p mypackage -o stubs/步骤 2:启用 mypy
bash
mypy --install-types
mypy src/ --ignore-missing-imports步骤 3:逐步修复
从核心模块开始,逐个文件添加类型:
python
# 第1周:为公共 API 添加类型
# 第2周:为核心业务逻辑添加类型
# 第3周:为工具函数添加类型步骤 4:集成 CI
yaml
# .github/workflows/type-check.yml
- name: Type check
run: mypy src/小结
- mypy 是标准类型检查器
- pyright 性能更高,VS Code 集成
- 渐进类型 允许逐步添加类型
- Any 是动态类型逃生舱,应谨慎使用
# type: ignore临时绕过检查- typeshed 提供第三方库类型存根
参考: