BaseModel 模型
BaseModel 是 Pydantic 最核心的類別:繼承它、用型別提示宣告欄位,就得到一個在建立時自動驗證資料的模型。本頁說明如何宣告模型、建立物件的幾種方式、必填與選填欄位、型別轉換規則,以及模型物件常用的屬性與方法。
如何宣告一個模型?
from datetime import datetime
from pydantic import BaseModel
class User(BaseModel):
id: int # 必填
name: str # 必填
email: str | None = None # 選填,預設 None
tags: list[str] = [] # 選填,預設空串列(Pydantic 會為每個物件複製一份)
signup_ts: datetime | None = None
user = User(id=1, name="Alice", signup_ts="2026-10-11T09:30:00")
print(user.signup_ts) # 2026-10-11 09:30:00(字串已轉成 datetime)
print(user.tags) # []
規則很簡單:沒有預設值的欄位就是必填;有預設值(包含 None)的欄位是選填。
可變預設值是安全的
一般 Python 類別寫 tags: list = [] 會讓所有物件共用同一個串列;Pydantic 會為每個物件深複製(deep copy)預設值,所以 = [] 是安全的寫法。
建立模型物件有哪幾種方式?
| 方式 | 適用情境 |
|---|---|
User(id=1, name="Alice") |
在程式碼中直接建立,參數用關鍵字傳入 |
User.model_validate({"id": 1, "name": "Alice"}) |
資料已經是 dict(例如 json.load 的結果) |
User.model_validate_json('{"id": 1, "name": "Alice"}') |
資料是 JSON 字串或 bytes,直接解析+驗證,比先 json.loads 更快 |
from pydantic import BaseModel
class User(BaseModel):
id: int
name: str
raw = '{"id": 7, "name": "Bob"}'
user = User.model_validate_json(raw)
print(user.id, user.name) # 7 Bob
Pydantic 會自動轉換型別嗎?
會。預設的「寬鬆模式」(lax mode)會做合理且不遺失資訊的轉換:
| 欄位型別 | 會被接受的輸入 | 會被拒絕的輸入 |
|---|---|---|
int |
3、"3"、3.0 |
"3.5"、3.5、"abc" |
float |
1.5、"1.5"、2 |
"abc" |
bool |
True、"true"、"yes"、"1"、1 |
"maybe"、2 |
str |
"abc" |
123(數字不會自動轉成字串) |
datetime |
ISO 8601 字串、Unix 時間戳 | "明天" |
注意 3.5 傳給 int 會失敗,因為轉換會遺失小數部分。需要完全不轉換時可以開啟嚴格模式(strict mode),見 model_config 模型設定。
驗證失敗時會怎樣?
建立物件時只要有任一欄位不合法,就會丟出 pydantic.ValidationError,而且會一次列出所有錯誤,而不是只回報第一個:
from pydantic import BaseModel, ValidationError
class User(BaseModel):
id: int
name: str
try:
User(id="abc")
except ValidationError as e:
print(e)
輸出會指出 id 不是合法整數、name 欄位缺少。如何讀懂與處理這些錯誤,見 ValidationError 錯誤處理。
模型物件有哪些常用屬性與方法?
V2 的模型方法一律以 model_ 開頭,避免和你自己的欄位名稱衝突:
| 方法/屬性 | 作用 |
|---|---|
model_dump() |
轉成 dict |
model_dump_json() |
轉成 JSON 字串 |
model_copy(update={...}) |
複製物件,可同時修改部分欄位 |
model_fields_set |
建立時「明確傳入」的欄位名稱集合 |
User.model_fields |
類別上的欄位定義資訊 |
User.model_json_schema() |
產生 JSON Schema |
from pydantic import BaseModel
class User(BaseModel):
id: int
name: str
role: str = "member"
user = User(id=1, name="Alice")
admin = user.model_copy(update={"role": "admin"})
print(user.model_dump()) # {'id': 1, 'name': 'Alice', 'role': 'member'}
print(admin.role) # admin
print(user.model_fields_set) # {'id', 'name'}(role 用的是預設值)
修改屬性時不會重新驗證
預設情況下 user.id = "abc" 不會報錯。需要在賦值時也驗證,請在 model_config 設定 validate_assignment=True;需要不可變物件則設定 frozen=True,見 model_config 模型設定。
推薦影音
pixegami:Pydantic 入門教學
簡述:約 11 分鐘,從「Python 動態型別帶來的問題」切入,依序示範建立模型、驗證資料、自訂欄位驗證、JSON 序列化,最後比較 Pydantic 與 dataclass,很快就能建立對 BaseModel 的整體印象。
相關資料
- Pydantic 官方文件:Models
- Pydantic 官方文件:Conversion Table:完整的型別轉換規則
- 下一步:型別與 Field