Ba thứ giải quyết ba nhu cầu khác nhau, nhìn theo ranh giới dữ liệu:
NamedTuple — bản ghi bất biến, nhẹ, có thể unpack và dùng làm key của dict. Hợp cho giá trị trả về nhiều thành phần, cấu hình chỉ đọc, toạ độ/khoảng thời gian.
from typing import NamedTuple
class Range(NamedTuple):
start: int
end: int
lo, hi = Range(0, 10) # tuple unpacking works@dataclass — domain object bên trong hệ thống: mutable được, có default, __post_init__, __eq__ sinh sẵn, không phụ thuộc thư viện ngoài. Không validate kiểu lúc chạy — khai báo age: int vẫn nhận "abc" bình thường.
pydantic.BaseModel — dùng ở rìa hệ thống, nơi dữ liệu đến từ nguồn không tin cậy: request body, JSON, biến môi trường, response của API bên thứ ba. Nó parse, ép kiểu theo quy tắc, validate và sinh lỗi có cấu trúc; FastAPI dùng chính nó để sinh OpenAPI. Đổi lại là thêm dependency và chi phí khởi tạo object cao hơn.
Cách chọn quen dùng: pydantic ở lớp API/config, dataclass ở lớp domain/service, NamedTuple cho giá trị nhỏ bất biến. Đừng đẩy pydantic model xuống vòng lặp nóng khi dữ liệu đã được validate.