第十三章:常见坑与最佳实践
13.1 新手高频坑
- 可变默认值:
tags: list = []❌ →Field(default_factory=list)✅ str | None不给默认值:以为可以省略,实际是必填。记得= None。- 钱用 float:精度丢失。用
Decimal。 - v1/v2 API 混用:
parse_obj/validator/dict()都是 v1,v2 是model_validate/field_validator/model_dump()。网上教程混杂,看到旧写法要能识别。 - 过度信任自动转换:宽松模式下
True可以变成1、"True"。对关键字段(尤其是 bool、int 混用时)考虑strict=True。 - 验证器里抛别的异常:验证器里只抛
ValueError(或AssertionError),抛其他异常会直接穿透,不会被包装成ValidationError。 - 循环导入:模型互相引用时用
from __future__ import annotations+ 必要时model_rebuild()。
13.2 性能建议
- Pydantic v2 本身已经很快(Rust 核心),但在循环里反复创建模型仍有开销。批量校验用
TypeAdapter(list[MyModel]).validate_python(data)一次搞定。 - 不需要校验的内部数据,别硬套 BaseModel,用 dataclass 或 NamedTuple。
model_construct()可以跳过校验直接建实例,仅用于 你百分之百确定数据干净 的性能敏感路径。
13.3 工程实践
- 一个项目一套基类:定义自己的
class AppModel(BaseModel)统一配置(extra、str_strip_whitespace等),所有模型继承它。 - 读写分离:请求模型(CreateXxxReq)和响应模型(XxxResp)分开定义,响应模型开
from_attributes=True。 - 错误信息给用户看时要翻译:
e.errors()返回结构化列表,自己加工成友好提示,别把原始英文直接甩给终端用户。 - 模型即文档:认真写
description和 docstring,半年后你会感谢自己。