这两种写法在 Pydantic 中最终实现的字段校验 / 元数据效果完全等价,但在语法本质、语义清晰度、复用能力、生态兼容性上有显著区别,核心差异源于一个是「Pydantic 自定义默认值写法」,一个是「Python 标准类型注解写法」。

一、语法本质不同

1. 传统写法:temperature: float = Field(description="Degrees Celsius.")

  • 属于 Pydantic 自创的「默认值占位」语法:利用赋值运算符 =,将 Field() 返回的 FieldInfo 对象作为「特殊默认值」传递。
  • Pydantic 解析模型时会识别出这是元数据而非真实默认值,从中提取 description、校验规则等配置。
  • 非 Python 标准语法,是 Pydantic 生态特有的用法。

2. Annotated 写法:temperature: Annotated[float, Field(description="Degrees Celsius.")]

  • 基于 PEP 593 标准的 typing.Annotated,是 Python 类型系统原生支持的「类型 + 元数据」注解方式。
  • Field 作为元数据附加在类型 float 上,不依赖赋值运算符,元数据和类型本身绑定在一起。
  • 属于 Python 通用标准语法,不局限于 Pydantic。

二、核心差异对比

表格
 
维度float = Field(...)Annotated[float, Field(...)]
语法标准 Pydantic 自定义用法 Python 官方标准(PEP 593)
必填语义直观性 有歧义:视觉上像「有默认值」,实际无 default 参数时仍是必填字段 语义清晰:注解本身就代表「必填 float 字段」,没有赋值误导
元数据复用 无法直接复用,每个字段都要重复写一遍 Field 参数 可定义类型别名批量复用,适合重复字段
多库兼容 仅 Pydantic 可识别 FastAPI、Typer、Litestar 等全生态通用,同一条注解可被多个库读取
类型检查友好度 需 Pydantic 插件,否则 mypy/pyright 可能报类型不匹配 原生支持,无需插件即可正确推断类型
版本兼容 Pydantic v1 /v2 全支持 Pydantic v2 原生完善支持,v1 支持有限

三、关键细节补充

1. 带默认值时的写法差异

如果字段需要默认值,两种写法的推荐范式不同:
1 # 传统写法:默认值写在 Field 内部
2 temperature: float = Field(default=25.0, description="Degrees Celsius.")
3 
4 # Annotated 写法:推荐默认值放在赋值右侧,元数据和默认值分离
5 temperature: Annotated[float, Field(description="Degrees Celsius.")] = 25.0

Annotated 写法将「类型 + 校验元数据」与「默认值」彻底分离,语义更清晰。

2. 复用能力(Annotated 最大优势)

对于重复出现的字段定义,Annotated 可以预先封装成类型别名,大幅减少重复代码:
 1 from typing import Annotated
 2 from pydantic import BaseModel, Field
 3 
 4 # 预先定义可复用的温度类型
 5 Temperature = Annotated[float, Field(description="摄氏度", ge=-273.15, le=1000)]
 6 
 7 class Weather(BaseModel):
 8     current_temp: Temperature  # 直接复用,自带描述和上下限校验
 9     forecast_temp: Temperature  # 同上
10     body_temp: Temperature      # 同上

传统 = Field(...) 写法无法实现这种批量复用。

3. 多框架协同

Annotated 是 Python 生态通用标准,同一个注解可以同时承载多个框架的元数据:
1 from fastapi import Query
2 from pydantic import Field
3 
4 # 同时被 FastAPI 和 Pydantic 识别
5 TempQuery = Annotated[float, Query(description="API查询参数"), Field(ge=-273.15)]

传统写法无法做到这种跨框架元数据合并。


四、总结与选型建议

  • 功能等价:只要 Field 内的参数一致,两种写法最终的校验、序列化、OpenAPI 生成效果完全相同。
  • 推荐场景:
    • 老项目兼容 Pydantic v1、简单小模型 → 用传统 = Field(...)
    • 新项目、Pydantic v2、需要复用字段、配合 FastAPI/Typer 等框架 → 优先用 Annotated 写法,也是 Pydantic v2 官方推荐的主流写法。