メインコンテンツへスキップ
友田 陽大
Pydantic・型安全バリデーション
Python
Pydantic
型安全
データモデリング
パフォーマンス
アーキテクチャ設計

Pydantic vs dataclasses vs TypedDict vs attrs vs msgspec:Pythonデータモデリング選定ガイド(2026)

Pythonのデータモデリング5択を公式情報に基づき公平に比較。dataclasses/TypedDictは実行時検証なし、attrsは検証オプトインで直列化なし、msgspecは速度特化、Pydanticは検証+スキーマ+エコシステムのバランス。実行時検証・直列化・JSON Schema・性能・エコシステムの軸と意思決定フローで、案件に最適な選択を示します。

公開日
読了時間
11分
著者
友田 陽大
シェア

導入:問いは「どれが最強か」ではなく「何が要るか」

「Python のデータモデルは結局どれを使えばいい? Pydantic? dataclass?」——これはよく聞かれる質問ですが、問い自体が少しずれています。5 つの選択肢は、解いている問題が違うからです。dataclasses と Pydantic を「どちらが優れているか」で比べるのは、ドライバーとインパクトレンチを比べるようなものです。

本記事は、dataclassesTypedDictattrsmsgspecPydantic の 5 つを、公式の一次情報に基づいて公平に比較します。Pydantic を売り込むための記事ではありません——むしろ「ここでは Pydantic は要らない」という判断こそ、エンジニアの信頼性を示します。marshmallow との比較は marshmallow vs Pydantic で扱っているので、本記事は Python 標準ライブラリ+速度特化ライブラリとの比較に絞ります。

最初に、選定を貫くたった一つの問いを提示します——「そのデータは、信頼できない外部から来るか?」。来るなら、実行時に値を検証するライブラリが要ります。来ない(コード内部で生成・管理される信頼できるデータ)なら、検証は不要なコストです。この軸を念頭に読み進めてください。


1. 全体像:5 つを一枚の表で

まず結論の俯瞰図です。各セルは各プロジェクトの公式情報に基づきます。

Pydantic v2dataclassesTypedDictattrsmsgspec
実行時検証✅ 中核機能❌ なし❌ なし(静的のみ)△ オプトイン✅ デコード時
直列化(JSON等)✅ 内蔵asdictのみ(JSON非対応)❌(実体は dict)❌(別途 cattrs)✅ JSON/msgpack/YAML/TOML
JSON Schema 生成
性能の位置づけ「最速級」/Rust製コア検証なし=オーバーヘッドなし同上公称なし速度特化(公称最速級)
設定管理✅ pydantic-settings
標準 / サードパーティサードパーティ標準標準サードパーティサードパーティ
主な用途API・境界・設定・LLM出力内部の構造体辞書の静的型付け柔軟なクラス生成高スループット直列化

ポイントは最初の 2 行です。「実行時検証」と「直列化」の有無が、選定をほぼ決めます。以下、1 つずつ公式情報で確認します。


2. dataclasses:標準ライブラリの構造体(検証はしない)

Python 標準の @dataclass は、__init__ / __repr__ / __eq__ などを自動生成します。依存ゼロで構造化レコードが書けるのが最大の利点です。

from dataclasses import dataclass


@dataclass
class InventoryItem:
    name: str
    unit_price: float
    quantity_on_hand: int = 0

ただし、型アノテーションは実行時に検証されません。公式ドキュメントは明言しています——「(2 つの例外を除き)@dataclass はアノテーションで指定された型を一切調べない」

# 型は str/float/int だが、検証されないので "壊れた" インスタンスが普通に作れる
item = InventoryItem(name=123, unit_price="無料", quantity_on_hand=None)  # エラーにならない

asdict / astuple で dict・tuple へ変換できますが、JSON 直列化や JSON Schema 生成はありません

💡 dataclasses を選ぶとき:データの出どころが信頼できる内部(自分のコードが生成する設定オブジェクト、計算の中間結果、DTO など)で、検証も直列化も要らない場合。標準ライブラリだけで完結し、依存を増やさない——KISS と YAGNI に最も忠実な選択です。


3. TypedDict:辞書に「静的な型」を付ける

TypedDict は、辞書のキーと値に型ヒントを与えます。しかし実行時には何も起きません。公式の言葉どおり——「実行時には TypedDict のインスタンスは単なる dict」であり、「この期待は実行時には検査されず、型チェッカーによってのみ強制される」

from typing import TypedDict


class Point2D(TypedDict):
    x: int
    y: int
    label: str


p: Point2D = {"x": 1, "y": 2, "label": "A"}  # 実体はただの dict。mypy だけが型を見る

💡 TypedDict を選ぶとき:JSON 由来の辞書ペイロードに静的型チェック(mypy/Pyright)だけを効かせたい場合。クラスを増やさず、実行時の振る舞いも変えずに、エディタ補完と静的検査を得られます。なお Pydantic は TypedDict を検証対象にできるので、「静的には TypedDict、境界では Pydantic で検証」という併用も可能です(パフォーマンス最適化ガイド で触れたとおり、Pydantic 公式も「TypedDict はネストモデルより約 2.5 倍速い」と認めています)。


4. pydantic.dataclasses:dataclass 構文に検証を足す

「dataclass の書き心地のまま、検証だけ欲しい」——その中間解が pydantic.dataclasses です。標準の @dataclass を Pydantic 版に差し替えると、検証と型強制が効くようになります。

from datetime import datetime
from typing import Optional
from pydantic.dataclasses import dataclass


@dataclass
class User:
    id: int
    name: str = "John Doe"
    signup_ts: Optional[datetime] = None


user = User(id="42", signup_ts="2032-06-21T12:00")
# id="42" → 42 に型強制、signup_ts は datetime にパースされる

公式は*「BaseModel を使いたくない場合、標準の dataclass で同じデータ検証が得られる」と説明しつつ、「Pydantic dataclass は Pydantic モデルの置き換えではない」*とも明記しています。model_config の一部や BaseModel のメソッド群(model_dump 等)はそのままは使えません。

💡 pydantic.dataclasses を選ぶとき:既存の dataclass ベースのコードに、最小の変更で検証を導入したい場合。あるいは「dataclass の構文が好きだが、外部入力の検証は欲しい」場合。新規で API 境界をがっつり作るなら、次章以降の BaseModel のほうが機能が揃っています。


5. attrs:成熟したクラスビルダー(検証はオプトイン、直列化は別)

attrs は dataclass の源流ともいえる成熟ライブラリで、クラス生成を強力かつ柔軟に制御できます(slots・コンバータ・バリデータなど)。検証はオプトイン——バリデータを明示的に付けたフィールドだけが検証されます。

from attrs import define, field
import attrs


@define
class Color:
    value = field(validator=attrs.validators.instance_of(int))

    @value.validator
    def _fits_byte(self, attribute, value):
        if not 0 <= value < 256:
            raise ValueError("0〜255 の範囲で指定してください")

重要なのは、attrs は直列化ライブラリではないこと。公式が*「attrs は本格的な直列化ライブラリではない…姉妹プロジェクトの cattrs を見てほしい」*と述べているとおり、JSON との相互変換は cattrs が担います(関心の分離)。JSON Schema 生成も標準ではありません。

💡 attrs を選ぶとき:クラス生成を細かく制御したい(スロット最適化、コンバータ、複雑な __init__ ロジック)、かつ直列化を意図的に分離したい(cattrs と組む)場合。Pydantic より「クラスの作り方」そのものへの自由度が高い一方、検証・スキーマ・エコシステムは自分で組み立てる必要があります。


6. msgspec:速度に全振りした検証+直列化

msgspec は、直列化と検証の速度に特化したライブラリです。msgspec.Struct を定義すると、JSON・MessagePack・YAML・TOML の相互変換と、デコード時の型検証が極めて高速に行われます。

import msgspec


class User(msgspec.Struct):
    name: str
    groups: set[str] = set()
    email: str | None = None


msgspec.json.encode(User("alice", groups={"admin"}))
# b'{"name":"alice","groups":["admin"],"email":null}'

msgspec.json.decode(b'{"name":"bob","groups":[123]}', type=User)
# msgspec.ValidationError: Expected `str`, got `int` - at `$.groups[0]`

msgspec は JSON Schema 生成(msgspec.json.schema)も備えます。性能について、公式は強気な数値を自社ベンチマークとして掲げています——「JSON/MessagePack 実装は Python で最速級」「msgspec は orjson が単にデコードするより速くデコード&検証する」「構造体は一般的な操作で 5〜60 倍速い」

⚠️ 数値はベンダー公称である:これらの倍率は msgspec 自身のベンチマークによる主張であり、第三者が中立に測ったものではありません。自分のワークロードで測ってから採用してください。一方 Pydantic 公式は性能ページの冒頭で*「多くの場合 Pydantic はボトルネックにならない」*と述べています。「速さが本当に律速になっているか」を計測で確かめるのが先決です(Pydantic パフォーマンス最適化ガイド 参照)。

💡 msgspec を選ぶとき:高スループットな API・メッセージキュー・巨大 JSON の取り込みで、直列化+検証が実測のボトルネックになっている場合。速度特化のサードパーティを導入できるなら強力です。


7. Pydantic:検証・スキーマ・エコシステムのバランス

Pydantic は、実行時検証・JSON Schema 生成・pydantic-settings・広大なエコシステムを一つにまとめた、いわば「境界の既定値」です。中核の pydantic-core は Rust 製で、公式は*「Python で最速級のデータ検証ライブラリの一つ」*と位置づけます。

from pydantic import BaseModel, Field


class User(BaseModel):
    id: int
    name: str = Field(min_length=1)
    email: str


User.model_validate({"id": "42", "name": "alice", "email": "a@example.com"})
# 検証+型強制+(必要なら)JSON Schema 生成+直列化がワンストップ

Pydantic の真の強みは、機能単体よりもエコシステムにあります。FastAPI・SQLModel・Django Ninja・LangChain・PydanticAI が Pydantic を土台にしており、PyPI 上で約 8,000 のパッケージが Pydantic に依存しています。「検証したモデルが、そのまま API スキーマになり、設定になり、LLM の構造化出力になる」——この一気通貫が、他にはない価値です。

💡 Pydantic を選ぶとき:外部入力を扱う境界(HTTP API、外部 API レスポンス、設定、LLM 出力)。検証・直列化・スキーマ・設定を一貫した型で扱いたい場合。FastAPI を使うなら事実上の標準です。「迷ったら Pydantic」が成立するのは、この守備範囲の広さゆえです。


8. 意思決定フローチャート

最後に、選定を 1 枚のフローに落とします。

  1. 実行時に値を検証する必要があるか?(データは信頼できない外部から来るか)
    • いいえ → 2 へ。
    • はい → 3 へ。
  2. (検証不要)辞書のまま静的型付けしたい?
    • はい → TypedDict
    • いいえ(クラスが欲しい)→ dataclasses(細粒度の制御が要るなら attrs
  3. (検証必要)直列化の速度が実測のボトルネックか?
    • はい → msgspec
    • いいえ → 4 へ。
  4. JSON Schema・設定管理・FastAPI 等のエコシステムが欲しい?
    • はい → Pydantic(新規 API 境界の既定)
    • dataclass 構文を保ちたいだけ → pydantic.dataclasses
    • クラス生成の自由度+直列化分離が欲しい → attrs + cattrs
状況推奨
FastAPI で API を作るPydantic(事実上の標準)
設定・シークレット管理pydantic-settingsガイド
LLM の構造化出力Pydantic / PydanticAIガイド
検証不要な内部 DTOdataclasses
辞書の静的型付けTypedDict
直列化が律速の高スループットmsgspec
クラス生成の細かな制御attrs + cattrs

結論:道具は問題に合わせて選ぶ

5 つの選択肢は競合ではなく、解く問題のレイヤーが違う道具です。本記事の要点を再掲します。

  1. 選定の第一問は**「外部入力を検証するか」dataclassesTypedDict検証しない**(公式明記)。
  2. dataclasses は標準の構造体、TypedDict は辞書の静的型付け——いずれも信頼できる内部データ向け。
  3. attrs は検証オプトイン+直列化分離(cattrs)、msgspec は速度特化(ただし倍率はベンダー公称)。
  4. Pydantic は検証・スキーマ・設定・エコシステムのバランスで、境界の既定値
  5. 迷ったらフローチャート——検証の要否 → 速度の律速 → エコシステムの必要性、の順で絞る。

「最強のライブラリ」を探すより、目の前のデータがどこから来て、何を保証したいのかを見極めることが、保守性とコスト効率の高い設計につながります。それが分かっていれば、Pydantic を選ぶときも、あえて標準の dataclass で済ませるときも、自信を持って説明できます。

各プロジェクトの一次情報:


技術選定・データモデリング設計のご相談

筆者は、経済産業大臣賞を受賞した B2B SaaS をはじめ、複数の本番システムで「どこに何の道具を使うか」の技術選定を主導してきました。データモデリングの選定は、性能・保守性・チームの学習コスト・エコシステムを天秤にかける意思決定です。要件に対して過不足のないライブラリ選定と、それに基づく型安全なアーキテクチャ設計を、生成 AI を活用して高速かつ高品質に支援します。Python バックエンドの技術選定について、お気軽にご相談ください。

友田

友田 陽大

経済産業大臣賞 受賞プロダクト開発者。TypeScript + Python + AWS で、SaaS・業界DX・ 実用レベルの生成AI(RAG)を、要件定義からインフラ・運用まで一人で完遂します。

この記事で解説した技術の適用事例

経済産業大臣賞受賞 | 木材流通業界のDXを実現したB2BサブスクリプションSaaS

ケーススタディを見る