TypedDict は PEP-589 で紹介され、Python 3.8 に導入された。主に辞書の型注釈を作成するために使われる。
dataclass や pydantic を使って「レコード」型データを表現する代わりに、TypedDict は辞書の柔軟性を活かし、フィールドが欠ける可能性がある状況で有利。
- たとえば、
Movie クラスを定義し、movie 変数に Movie 型の辞書を代入する方式。
class Movie(TypedDict):
title: str
movie: Movie = {"title": "Avatar"}
Non-totality
TypedDict は、フィールドが欠ける可能性があることを表す概念である non-totality をサポートしている。HTTP PATCH エンドポイントの実装時に有用。
dataclass にはフィールド欠落という概念がなく、不自然になる場合がある。
TypedDict では total=False に設定することで、フィールド欠落を柔軟に扱える。
- PEP-655 では
Required と NotRequired により個別フィールドを指定できる。
TypedDict を **kwargs として使う
- PEP-692 は、
TypedDict を使って可変キーワード引数を入力できるようにする。
TypedDict を使うとコードが冗長に見えることもあるが、複数の関数定義で再利用する場合には有用。
- Non-totality と組み合わせるとさらに強みを発揮する。
pytest.fixture をカスタマイズしつつ、一部の引数をそのまま渡すようなシナリオなど。
- Sentinel 値で似た挙動を実装することも可能だが、型アノテーションが不自然になることがある。
依存性注入に TypedDict を使う
- PEP-692 は、
TypedDict を使った関数呼び出し時に型検査を可能にする。
- 多くのリソースが一部の依存関係を共有する状況で有用。
- すべてのリソースの kwargs をまとめたものに近い
TypedDict を定義する。
- リソースが任意の引数を受け取るように書き換えたうえで、
TypedDict によって依存性注入を行う。
- 型システムを通じて、依存性注入時の引数の誤りや不足を検査できる。
- リソースのシグネチャ変更は理想的ではないが、依存性注入フレームワークを導入するよりは小さな変更。
- 静的型検査をサポートしないフレームワークは多い。
今後の機能
- PEP-728 は、追加項目の型を定義し、追加項目を許可しない閉じた辞書を定義できるようにする。
- PEP-705 は、読み取り専用項目を指定できるようにする(発表時点によってはすでにリリース済みかもしれない)。
- 直感的には互換であるはずの別の
TypedDict 同士で、潜在的な変更や削除による問題が起こりうる状況に対応する。
GN⁺のまとめ
TypedDict は辞書の柔軟性を活かし、フィールドが欠ける可能性がある状況で有利。
TypedDict は dataclass や pydantic のような他のデータ構造よりも柔軟な選択肢を提供する。
- ドメインに応じて適切なツールを選びつつ、
TypedDict の利点も念頭に置くべき。
2件のコメント
外部からデータがjson形式で入ってきたり、Pythonの外部にexportすることが多い場合はTypedDictを使うとよく、そうでなければ構造化されたdataclassやNamedTupleを使うことをおすすめします。
Hacker Newsの意見
動的型付けを好む人たちが、型システムの重要性にますます気づきつつある
TypedDictの代わりにdataclass(slots=True)を使う理由["foobar"]の代わりに.foobarを使えるので、手首への負担が少ない型を強制するシステムがなければ、
TypedDictは何の役割も果たさないPydanticのようなツールを使う必要がある「thank you think」というタイトルは、あまりにも無礼に聞こえる
サブスクリプションに関する文の "None" の意味が不明確
TypedDictに関する個人的な経験TypedDictを使っているTypedDictの機能は良いが、宣言構文が複雑