型別與 Field
型別決定一個欄位「是什麼」,Field() 決定它「還要滿足什麼條件」:數值範圍、字串長度、正規表示式、預設值、別名與說明文字。本頁整理 Pydantic 最常用的欄位型別、Field 的常用參數,以及用 Annotated 建立可重複使用的型別。
有哪些常用的欄位型別?
Pydantic 支援所有標準 Python 型別,另外提供一些實用的專用型別:
| 類別 | 型別 | 說明 |
|---|---|---|
| 基本 | int、float、str、bool、bytes |
依寬鬆模式轉換 |
| 容器 | list[T]、tuple[T, ...]、dict[K, V]、set[T] |
每個元素都會驗證 |
| 可選 | T \| None |
允許 None;是否必填仍看有沒有預設值 |
| 多選一 | Literal["a", "b"]、Enum |
限定只能是特定值 |
| 聯集 | int \| str |
依序嘗試,取最合適者 |
| 時間 | datetime、date、time、timedelta |
接受 ISO 8601 字串 |
| 其他 | UUID、Decimal、Path |
標準函式庫型別 |
| Pydantic 專用 | HttpUrl、EmailStr、SecretStr、PositiveInt |
常見格式的現成驗證 |
from typing import Literal
from pydantic import BaseModel, HttpUrl, PositiveInt, SecretStr
class Account(BaseModel):
username: str
password: SecretStr # 印出時會顯示 '**********'
plan: Literal["free", "pro"] = "free"
homepage: HttpUrl | None = None
quota: PositiveInt = 10
acc = Account(username="alice", password="s3cret", homepage="https://fates.cc")
print(acc.password) # **********
print(acc.password.get_secret_value()) # s3cret
EmailStr 需要先安裝 pydantic[email],見 安裝與環境。
Field 可以設定哪些限制?
from pydantic import BaseModel, Field
class Product(BaseModel):
name: str = Field(min_length=1, max_length=50)
price: float = Field(gt=0, description="售價,必須大於 0")
stock: int = Field(default=0, ge=0)
sku: str = Field(pattern=r"^[A-Z]{3}-\d{4}$")
tags: list[str] = Field(default_factory=list, max_length=5)
p = Product(name="鍵盤", price=1290, sku="KBD-0001")
print(p)
| 參數 | 適用 | 意義 |
|---|---|---|
default / default_factory |
全部 | 預設值;可變物件或需要每次重新產生(例如 datetime.now)時用 default_factory |
gt、ge、lt、le |
數值 | 大於、大於等於、小於、小於等於 |
multiple_of |
數值 | 必須是某數的倍數 |
min_length、max_length |
字串、容器 | 長度限制 |
pattern |
字串 | 正規表示式 |
alias |
全部 | 外部資料使用的欄位名稱 |
description、examples、title |
全部 | 寫進 JSON Schema,FastAPI 文件與 LLM 都會讀到 |
exclude |
全部 | 輸出時排除此欄位 |
外部資料的欄位名稱跟 Python 不一樣怎麼辦?
外部 API 常用 camelCase 或含有連字號的名稱,可以用 alias 對應:
from pydantic import BaseModel, ConfigDict, Field
class Repo(BaseModel):
model_config = ConfigDict(validate_by_name=True)
full_name: str = Field(alias="fullName")
star_count: int = Field(alias="stargazers_count")
repo = Repo.model_validate({"fullName": "pydantic/pydantic", "stargazers_count": 20000})
print(repo.full_name) # pydantic/pydantic
print(repo.model_dump(by_alias=True)) # {'fullName': 'pydantic/pydantic', 'stargazers_count': 20000}
validate_by_name=True 讓你在 Python 程式中也能用 full_name=... 建立物件。整個模型都要轉成 camelCase 時,用 alias_generator 比逐一寫 alias 省事,見 model_config 模型設定。
什麼是 Annotated?為什麼推薦使用?
Annotated[型別, 額外資訊] 是標準函式庫的寫法,Pydantic 讀取其中的 Field 與驗證器。好處是把限制條件做成可重複使用的型別:
from typing import Annotated
from pydantic import BaseModel, Field
Username = Annotated[str, Field(min_length=3, max_length=20, pattern=r"^[a-z0-9_]+$")]
Percentage = Annotated[float, Field(ge=0, le=100)]
class Student(BaseModel):
username: Username
score: Percentage
class Teacher(BaseModel):
username: Username # 重複使用,不必再寫一次限制
print(Student(username="alice_01", score=95.5))
Annotated 也是在 list[...] 裡限制每個元素的方法,例如 list[Annotated[int, Field(gt=0)]] 表示「每個元素都必須是正整數」。
推薦影音
Studycamp Taiwan:Pydantic V2 Essentials(中文)
簡述:台灣 Studycamp 社群的 Pydantic V2 Essentials 讀書會導讀錄影(第一週:介紹與基礎),以中文講解 V2 的基本觀念,適合偏好中文講解的讀者搭配本頁閱讀。