导航菜单

  • 1.什么是MCP
  • 2.MCP架构
  • 3.MCP服务器
  • 4.MCP客户端
  • 5.版本控制
  • 6.连接MCP服务器
  • 7.SDKs
  • 8.Inspector
  • 9.规范
  • 10.架构
  • 11.协议
  • 12.生命周期
  • 13.工具
  • 14.资源
  • 15.提示
  • 16.日志
  • 17.进度
  • 18.传输
  • 19.补全
  • 20.引导
  • 21.采样
  • 22.任务
  • 23.取消
  • 24.Ping
  • 25.根
  • 26.分页
  • 27.授权
  • 28.初始化
  • 29.工具
  • 30.资源
  • 31.结构化输出
  • 32.提示词
  • 33.上下文
  • 34.StreamableHTTP
  • 35.参数补全
  • 36.引导
  • 37.采样
  • 38.LowLevel
  • 39.任务
  • 40.取消
  • 41.ping
  • 42.根
  • 43.分页
  • 44.授权
  • 45.授权
  • Keycloak
  • asyncio
  • contextlib
  • httpx
  • pathlib
  • pydantic
  • queue
  • starlette
  • subprocess
  • threading
  • uvicorn
  • JSON-RPC
  • z
  • 1. 什么是类型提示?
    • 1.1 什么是类型提示?
    • 1.2 为什么需要数据验证?
  • 2. 什么是 Pydantic?
  • 3. 安装
  • 4. 快速入门
    • 4.1 定义第一个模型
    • 4.2 验证失败会怎样?
  • 5. 常用字段类型
    • 5.1 基本类型
    • 5.2 带约束的数字类型
  • 6. 使用 Field 添加约束
    • 6.1 基本用法
    • 6.2 使用 Annotated(V2 推荐写法)
  • 7. 自定义验证器
    • 7.1 字段验证器
    • 7.2 跨字段验证(模型验证器)
  • 8. 数据解析与序列化
    • 8.1 转成字典和 JSON
    • 8.2 从字典和 JSON 解析
  • 9. TypeAdapter:验证单个类型
    • 9.1 基本用法
    • 9.2 验证字典类型
    • 9.3 序列化
  • 10. 常用配置
  • 11. 模型继承
  • 12. 常见异常
  • 13. 总结

1. 什么是类型提示? #

1.1 什么是类型提示? #

类型提示是 Python 3.6+ 的语法,用来标注变量、参数、返回值的类型。例如:

# 标注 name 是字符串类型
def greet(name: str) -> str:
    return f"Hello, {name}"

类型提示本身不会在运行时检查数据,它主要给 IDE 和静态检查工具用。真正的数据验证需要额外工具,Pydantic 就是其中之一。

1.2 为什么需要数据验证? #

程序经常要处理外部数据:用户输入、API 返回、配置文件等。这些数据可能格式错误、类型不对、越界等。如果直接使用,容易导致程序崩溃或产生隐蔽 bug。

Pydantic 的作用:你定义一个"数据模型"(有哪些字段、什么类型、有什么限制),Pydantic 在创建实例时自动验证,不符合就立刻报错,并给出清晰提示。

通俗比喻:就像填表时的"必填项""格式要求",Pydantic 帮你自动检查每一栏是否合格。

2. 什么是 Pydantic? #

Pydantic 是一个基于 Python 类型提示的数据验证库,特点是:

  • 写法简单:用类型注解定义模型,和写普通类差不多
  • 自动验证:创建实例时自动检查类型和约束
  • 易序列化:轻松转成字典、JSON,或从字典、JSON 解析回来

本教程基于 Pydantic V2(当前主流版本),所有示例均可直接运行。

3. 安装 #

pip install pydantic

安装完成后即可使用,无需额外配置。

4. 快速入门 #

4.1 定义第一个模型 #

用 BaseModel 定义模型,用类型注解定义字段。

# 导入 BaseModel
from pydantic import BaseModel

# 定义用户模型:继承 BaseModel
class User(BaseModel):
    # 必填字段:id 为整数,name 为字符串
    id: int
    name: str
    # 可选字段:age 默认为 18
    age: int = 18

# 创建实例时自动验证类型
user = User(id=1, name="Alice")
# 打印模型(会显示所有字段)
print(user)
# 访问属性
print(user.name)
# age 使用默认值
print(user.age)

4.2 验证失败会怎样? #

传入错误类型时,Pydantic 会抛出 ValidationError,并说明哪个字段有问题。

# 导入 BaseModel
from pydantic import BaseModel

# 定义模型
class User(BaseModel):
    id: int
    name: str
    age: int = 18

# 故意传入错误类型:id 应该是 int,却传了字符串
try:
    User(id="不是数字", name="Bob")
except Exception as e:
    # 打印验证错误信息
    print(e)

5. 常用字段类型 #

5.1 基本类型 #

支持 str、int、float、bool、list、dict 等标准类型。还可以用 Optional 表示"可以为 None"。

# 导入 BaseModel 和 Optional
from pydantic import BaseModel
from typing import Optional, List

# 定义商品模型
class Product(BaseModel):
    # 字符串
    name: str
    # 浮点数
    price: float
    # 字符串列表,默认空列表
    tags: List[str] = []
    # 可选:可以是 bool 或 None
    in_stock: Optional[bool] = None

# 创建实例
p = Product(name="苹果", price=3.5, tags=["水果", "新鲜"])
print(p.name, p.price, p.tags)

# 可选字段可以不传
p2 = Product(name="香蕉", price=2.0)
print(p2.in_stock)

5.2 带约束的数字类型 #

Pydantic 提供 PositiveInt(正整数)、NonNegativeInt(非负整数)等,自动拒绝不符合的值。

# 导入 BaseModel 和 PositiveInt
from pydantic import BaseModel
from pydantic import PositiveInt

# 定义模型,age 必须是正整数
class Person(BaseModel):
    name: str
    age: PositiveInt

# 正常创建
p = Person(name="小明", age=20)
print(p)

# 传入 0 或负数会报错(PositiveInt 要求必须大于 0)
try:
    Person(name="小红", age=-1)
except Exception as e:
    # 捕获 ValidationError 并打印
    print("验证失败:", e)

6. 使用 Field 添加约束 #

Field 可以为字段添加长度限制、取值范围、描述等。

6.1 基本用法 #

# 导入 BaseModel 和 Field
from pydantic import BaseModel, Field

# 定义商品模型
class Product(BaseModel):
    # ... 表示必填;min_length、max_length 限制字符串长度
    name: str = Field(..., min_length=1, max_length=50)
    # gt=0 表示大于 0,le=10000 表示小于等于 10000
    price: float = Field(..., gt=0, le=10000)
    # 可选,最大长度 200
    description: str = Field(default="", max_length=200)

# 正常创建
p = Product(name="手机", price=2999)
print(p)

# 价格超范围会报错
try:
    Product(name="电脑", price=99999)
except Exception as e:
    print("验证失败:", e)

常用约束:min_length、max_length(字符串)、gt、ge、lt、le(数值大小)。

6.2 使用 Annotated(V2 推荐写法) #

把约束写在类型注解里,更清晰。

# 导入 Annotated、BaseModel、Field
from typing import Annotated
from pydantic import BaseModel, Field

# 用 Annotated 把类型和约束写在一起
class Product(BaseModel):
    name: Annotated[str, Field(min_length=1, max_length=50)]
    price: Annotated[float, Field(gt=0, le=10000)]

# 创建实例
p = Product(name="键盘", price=199)
print(p)

7. 自定义验证器 #

7.1 字段验证器 #

用 @field_validator 对单个字段做自定义校验。

# 导入 BaseModel 和 field_validator
from pydantic import BaseModel, field_validator

# 定义用户模型
class User(BaseModel):
    name: str
    # 要求密码至少 6 位
    password: str

    # 验证 password 字段
    @field_validator("password")
    @classmethod
    def password_not_short(cls, v: str) -> str:
        # 长度不足则抛出 ValueError
        if len(v) < 6:
            raise ValueError("密码至少 6 位")
        return v

# 正常创建
u = User(name="Alice", password="123456")
print(u)

# 密码太短会报错(少于 6 位)
try:
    User(name="Bob", password="123")
except Exception as e:
    # 捕获 ValidationError
    print("验证失败:", e)

7.2 跨字段验证(模型验证器) #

用 @model_validator 在多个字段都验证完后,再做整体校验。

# 导入 BaseModel 和 model_validator
from pydantic import BaseModel, model_validator

# 定义模型:两次输入的密码必须一致
class PasswordForm(BaseModel):
    password1: str
    password2: str

    # mode='after' 表示所有字段验证完后执行
    @model_validator(mode="after")
    def passwords_match(self):
        if self.password1 != self.password2:
            raise ValueError("两次密码不一致")
        return self

# 一致时正常
f = PasswordForm(password1="abc123", password2="abc123")
print("验证通过")

# 两次密码不一致时报错
try:
    PasswordForm(password1="abc123", password2="abc456")
except Exception as e:
    # 捕获 ValidationError
    print("验证失败:", e)

8. 数据解析与序列化 #

8.1 转成字典和 JSON #

# 导入 BaseModel
from pydantic import BaseModel

# 定义模型
class User(BaseModel):
    id: int
    name: str
    age: int = 18

# 创建实例
user = User(id=1, name="Alice", age=20)

# 转成字典
user_dict = user.model_dump()
print("字典:", user_dict)

# 转成 JSON 字符串
user_json = user.model_dump_json()
print("JSON:", user_json)

8.2 从字典和 JSON 解析 #

# 导入 BaseModel
from pydantic import BaseModel

# 定义模型
class User(BaseModel):
    id: int
    name: str
    age: int = 18

# 从字典解析(会自动验证)
data = {"id": 2, "name": "Bob"}
user = User.model_validate(data)
print(user)

# 从 JSON 字符串解析
json_str = '{"id": 3, "name": "Charlie", "age": 25}'
user2 = User.model_validate_json(json_str)
print(user2)

9. TypeAdapter:验证单个类型 #

当你只需要验证单个类型(如 list[int]、dict[str, int]),而不想定义完整的 BaseModel 时,可以用 TypeAdapter。它同样支持验证、解析和序列化。

9.1 基本用法 #

# 导入 TypeAdapter
from pydantic import TypeAdapter

# 创建适配器:验证 list[int] 类型
adapter = TypeAdapter(list[int])

# 从 Python 数据验证并转换
result = adapter.validate_python([1, 2, 3])
print("验证结果:", result)

# 从 JSON 字符串解析
result2 = adapter.validate_json("[10, 20, 30]")
print("解析结果:", result2)

9.2 验证字典类型 #

# 导入 TypeAdapter
from pydantic import TypeAdapter

# 验证 dict[str, int]:键为字符串,值为整数
adapter = TypeAdapter(dict[str, int])
# 从字典验证
data = adapter.validate_python({"a": 1, "b": 2, "c": 3})
print("字典:", data)

# 从 JSON 解析
json_str = '{"x": 10, "y": 20}'
data2 = adapter.validate_json(json_str)
print("解析:", data2)

9.3 序列化 #

# 导入 TypeAdapter
from pydantic import TypeAdapter

# 验证 list[str]
adapter = TypeAdapter(list[str])
data = ["a", "b", "c"]

# 转成字典(对 list 来说就是 list 本身)
dumped = adapter.dump_python(data)
print("dump_python:", dumped)

# 转成 JSON 字符串(dump_json 返回 bytes,需 decode 成 str)
json_str = adapter.dump_json(data).decode()
print("dump_json:", json_str)

说明:TypeAdapter 适合"只关心一个类型"的场景,如 API 返回的 list、配置中的 dict。需要多个字段的结构化数据时,仍推荐用 BaseModel。

10. 常用配置 #

通过 model_config 可以调整模型行为。

# 导入 BaseModel 和 ConfigDict
from pydantic import BaseModel, ConfigDict

# 定义模型
class User(BaseModel):
    # 禁止创建后修改字段(类似 frozen)
    model_config = ConfigDict(frozen=True)

    id: int
    name: str

# 创建实例
user = User(id=1, name="Alice")
print(user)

# 尝试修改会报错
try:
    user.name = "Bob"
except Exception as e:
    print("修改失败:", e)

常用配置:frozen=True(不可变)、extra='forbid'(禁止额外字段)。

11. 模型继承 #

子类会继承父类的字段。

# 导入 BaseModel
from pydantic import BaseModel

# 父类:人
class Person(BaseModel):
    name: str
    age: int

# 子类:员工,继承 Person 并新增字段
class Employee(Person):
    employee_id: str

# 创建员工实例,需要填父类+子类的字段
emp = Employee(name="张三", age=30, employee_id="E001")
print(emp)

12. 常见异常 #

异常 何时抛出
ValidationError 数据不符合模型定义或约束
访问不存在的字段 模型未定义该字段

用 try/except 捕获 ValidationError 即可处理验证失败。

13. 总结 #

内容 要点
定义模型 继承 BaseModel,用类型注解定义字段
字段约束 用 Field 或 Annotated 添加长度、范围等
自定义验证 @field_validator 单字段,@model_validator 跨字段
序列化 model_dump() 转字典,model_dump_json() 转 JSON
解析 model_validate() 从字典,model_validate_json() 从 JSON
TypeAdapter 验证单个类型(如 list[int]、dict[str, int]),无需定义模型

记忆口诀:先定义模型,再创建实例;数据不对会立刻报错,转字典/JSON 用 model_dump 和 model_validate;单类型验证用 TypeAdapter。

← 上一节 pathlib 下一节 queue →

访问验证

请输入访问令牌

Token不正确,请重新输入