Python函数参数校验的核心是早暴露、清报错、快修复:入口集中校验,明确契约,用type hints+业务规则检查,抛出带上下文的异常,面向调用方设计友好错误信息。

Python函数参数校验不是“加不加装饰器”的选择题,而是“怎么让错误暴露得早、报得清、修得快”的工程实践。核心目标是:在函数入口处拦截非法输入,避免错误向深层逻辑蔓延,同时提供对调用方友好的提示。
明确参数契约,先写类型与取值范围
校验的前提是定义清楚“什么是合法”。不要默认用户会读文档,把约束直接写进函数逻辑或类型注解中:
- 用 type hints 声明基础类型(int, str, List[str]),配合 mypy 静态检查
- 对数值参数注明有效区间(如 0 )、字符串注明长度或正则模式(如 email: str 必须匹配 r".+@.+\..+")
- 对可选参数(Optional)明确 None 是否允许,以及它代表什么语义
入口处集中校验,拒绝“边跑边猜”
避免在函数中间某处突然抛出 ValueError 或访问 None 属性——那会让调用方难以定位问题源头。所有校验代码应放在函数最开始几行:
- 先检查必填项是否缺失(if name is None:)
- 再检查类型是否符合(if not isinstance(age, int):)
- 最后检查业务规则(if age 150:)
- 每条失败都抛出带上下文的 TypeError 或 ValueError,例如:raise ValueError(f"age must be between 0 and 150, got {age}")
合理使用工具,但别为校验而校验
小函数手动校验清晰直接;复杂接口可借助轻量工具提升一致性:
立即学习“Python免费学习笔记(深入)”;
- pydantic v2 的 @validate_call 适合高频、多参数、需 JSON Schema 兼容的场景
- beartype 提供运行时类型检查,开销低,适合作为开发/测试阶段的增强防护
- 避免在性能敏感路径(如循环内、高频 I/O 回调)中引入重型校验逻辑
- 生产环境若已通过上游服务(如 API 网关、DTO 层)完成强校验,函数内可降级为断言或仅保留关键业务规则
面向调用方设计错误信息
报错不是为了告诉机器哪里错了,而是帮人快速理解“我传错了什么、该怎么改”:
- 错误消息里包含:非法值本身、期望的格式/范围、参数名(不要只说“invalid input”)
- 对集合类参数,指出具体哪个元素出错(如 f"tags[2] = '{tags[2]}' is not a string")
- 避免暴露内部实现细节(如不要写“expected _internal_id_format”)
- 中文系统建议用中文报错,但关键术语(如参数名、类型名)保留英文,方便日志搜索和调试










