标题:Python 类型提示 + Pydantic 数据校验|Day9学习笔记

前言

学习 Day9 之前,建议先复习:


一、类型提示(Type Hints)

类型提示 = 给代码写说明书。Pydantic = 把说明书变成质检员。

类型提示是"写着好看",Pydantic 是"真的帮你检查"。

1.1 基础语法

name: str = "韩立"
age: int = 18
height: float = 1.75
is_student: bool = True

1.2 函数注解

def greet(name: str) -> str:
    return f"你好,{name}"

def print_info(name: str) -> None:
    print(f"名字:{name}")

1.3 容器类型(需要 import)

from typing import List, Dict, Tuple, Optional, Union

names: List[str]              # 字符串列表
scores: Dict[str, int]        # 键是字符串、值是整数
maybe: Optional[str]          # 可能是 str 或 None
id_or_name: Union[int, str]   # 可能是 int 或 str

1.4 重要提醒:类型提示不改变代码行为

def add(a: int, b: int) -> int:
    return a + b

# ❌ 不会报错!类型提示只是说明书
add("hello", "world")  

类型提示只是给人看的注释,不会实际校验数据类型!


二、Pydantic 数据校验

2.1 Pydantic 是什么?

Pydantic = 类型提示 + 自动校验。

你定义一个数据模型(继承 BaseModel),Pydantic 自动帮你检查传进来的数据对不对。

2.2 最简模板

from pydantic import BaseModel

class Student(BaseModel):
    name: str
    age: int
    score: float

# ✅ 正常数据
s1 = Student(name="韩立", age=18, score=85.5)

# ✅ 自动转换(字符串 "18" → 整数 18)
s2 = Student(name="张三", age="18", score="85.5")

# ❌ 无法转换 → 报错("十八" 不是数字)
s3 = Student(name="张三", age="十八", score="优秀")

2.3 嵌套模型

class NowWeather(BaseModel):
    temp: str
    text: str
    feelsLike: str

class WeatherResponse(BaseModel):
    now: NowWeather

# 使用
data = weather_resp.json()
weather = WeatherResponse(**data)
print(weather.now.temp)        # 对象属性取值,不再手动字典取值

2.4 Pydantic 报错长这样

ValidationError: 2 validation errors for WeatherResponse
now.temp
  Input should be a valid string [type=string_type, input_value=None]

一眼看出:哪个字段、什么问题、传了什么值


三、核心区别总结

对比项 普通类型提示 Pydantic
作用 写给人看 写给程序自动检查
数据不对 照样运行 自动报错
字符串转数字 不管 “18” 自动转 18
报错信息 没有 清楚告诉你哪里错了

四、实战:给天气查询加上数据模型

4.1 完整代码

from pydantic import BaseModel
import requests
import os
from dotenv import load_dotenv

load_dotenv()
API_KEY = os.getenv("API_KEY")
API_HOST = os.getenv("API_HOST")

# ── Pydantic 模型 ──
class WeatherData(BaseModel):
    temp: str
    text: str
    feelsLike: str

class WeatherResponse(BaseModel):
    now: WeatherData

# ── 查询函数 ──
def get_weather(city: str) -> dict:
    headers = {"X-QW-Api-Key": API_KEY}
    
    # 城市名 → 城市代码
    geo_url = f"https://{API_HOST}/geo/v2/city/lookup?location={city}"
    geo_data = requests.get(geo_url, headers=headers).json()
    city_id = geo_data["location"][0]["id"]
    
    # 城市代码 → 天气
    weather_url = f"https://{API_HOST}/v7/weather/now?location={city_id}"
    weather_resp = requests.get(weather_url, headers=headers)
    
    # 用 Pydantic 校验
    weather = WeatherResponse(**weather_resp.json())
    
    return {
        "city": city,
        "temperature": weather.now.temp,
        "description": weather.now.text,
        "feels_like": weather.now.feelsLike
    }

# ── 测试 ──
if __name__ == "__main__":
    result = get_weather("北京")
    print(f"{result['city']}{result['description']}{result['temperature']}°C")

4.2 代码对比

操作 之前(字典) 现在(Pydantic)
取温度 data["now"]["temp"] weather.now.temp
类型校验 ❌ 无 ✅ 自动校验
字段不存在 ❌ KeyError ✅ ValidationError
代码可读性 一般 清晰直观

五、你踩过的坑

坑 1:以为类型提示会校验数据类型

def add(a: int, b: int) -> int:
    return a + b

add("hello", "world")  # 不会报错!

原因:类型提示只是注释,不会实际执行校验。

解决:需要真正的数据校验时,用 Pydantic。

坑 2:Pydantic 字段名和 JSON 不匹配

class Weather(BaseModel):
    temp: str
    feelsLike: str  # JSON 里是 feelsLike,L 大写

# ❌ 大小写必须完全匹配
data = {"temp": "25", "feelslike": "27"}  # 报错

六、模板速查

Pydantic 基础模板

from pydantic import BaseModel

class MyModel(BaseModel):
    field1: str
    field2: int
    field3: float

# 使用
data = {"field1": "value", "field2": "123", "field3": "45.6"}
model = MyModel(**data)  # 自动校验和转换

嵌套模型模板

class Inner(BaseModel):
    a: str
    b: int

class Outer(BaseModel):
    inner: Inner

# 使用
outer = Outer(**{"inner": {"a": "hello", "b": 123}})
print(outer.inner.a)  # hello

七、一句话总结

类型提示是写给人看的说明书,Pydantic 是给程序用的质检员。

在 AI 应用开发中,LLM 返回的数据经常各种抽风(少字段、类型不对、多出乱七八糟的东西),Pydantic 就是帮你第一时间抓住这些问题,不让脏数据往下传。


系列文章

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐