TypedDictとは
TypedDictはPython 3.8で導入された機能であり、typingモジュールの一部です。これを使用すると、辞書の型ヒントを指定することができます。予期されるキーとそれに対応する値の型を示すことができます。TypedDictは実行時にこれらの型を強制するものではありません。代わりに、静的な型チェックツールに使用され、コードの可読性と保守性を向上させます。
TypedDictの作成
PythonでTypedDictを作成するのは簡単です。まず、typing
モジュールからTypedDict
クラスをインポートします。次に、TypedDict
を継承する新しいクラスとしてTypedDictを定義します。このクラスの内部で、キーとそれに対応する型を定義します。
ユーザープロファイルのための単純なTypedDictを作成してみます。
from typing import TypedDict
class UserProfile(TypedDict):
name: str
age: int
email: str
上記の例では、UserProfile
という名前のTypedDictを作成しました。この定義によれば、UserProfile
の型である辞書は、name
、age
、email
というキーを持ち、それぞれの型はstr
、int
、str
である必要があります。
UserProfile
TypedDictを定義したので、それを使用する方法を見てみます。
def display_user(profile: UserProfile) -> None:
print(f"Name: {profile['name']}")
print(f"Age: {profile['age']}")
print(f"Email: {profile['email']}")
user: UserProfile = {
'name': 'Alice',
'age': 30,
'email': 'alice@example.com'
}
display_user(user)
上記のコードでは、まずdisplay_user
という関数を定義し、UserProfile
の辞書を引数として受け取り、ユーザーの情報を出力します。次に、先ほど定義したUserProfile
TypedDictに基づいてユーザー辞書を作成し、display_user
をuser
を引数として呼び出しています。
関数シグネチャの型ヒントにより、display_user
関数が常に正しい型の辞書を受け取ることが保証されます。UserProfile
TypedDictに準拠しない辞書でdisplay_user
を呼び出そうとする場合(例えば、キーが欠けているか、キーの値が間違った型である場合)、タイプエラーが発生します。
TypedDictのオプションキー
前のセクションで作成したTypedDictでは、全てのキーが存在し、特定の型であることが要求されました。しかし、オプションキーを持つTypedDictを定義することも可能です。これは、TypedDictの定義でtotal
パラメータを使用することで実現できます。
ユーザープロファイルの中でメールアドレスがオプションの場合を考えてみます。UserProfile
の定義においてtotal=False
と設定することで表現できます。
from typing import TypedDict
class UserProfile(TypedDict, total=False):
name: str
age: int
email: str
これにより、UserProfile
はemail
キーを持っていても持っていなくても有効です。
def display_user(profile: UserProfile) -> None:
print(f"Name: {profile['name']}")
print(f"Age: {profile['age']}")
if 'email' in profile:
print(f"Email: {profile['email']}")
user: UserProfile = {
'name': 'Alice',
'age': 30
}
display_user(user)
上記のコードでは、display_user
関数を修正し、プロファイルにメールアドレスが存在する場合にのみメールアドレスを出力するようにしました。その後、メールアドレスのないユーザープロファイルを作成し、display_user(user_without_email)
をエラーなく実行しています。
ネストされたTypedDict
TypedDictは、より複雑なデータ構造を表現するためにネストさせることもできます。ユーザープロファイルに住所情報が含まれるシナリオを考えてみます。住所情報自体がいくつかのフィールドを持つ辞書であるとします。
from typing import TypedDict
class Address(TypedDict):
street: str
city: str
state: str
zip_code: str
class UserProfile(TypedDict):
name: str
age: int
email: str
address: Address
上記のコードでは、Address
というTypedDictを定義し、それをUserProfile
の定義で使用しています。これにより、UserProfile
はaddress
というキーを含み、その値はAddress
というTypedDictである必要があります。
TypedDictと継承
TypedDictは継承もサポートしています。これは、複数の種類の辞書がいくつかのフィールドを共有しつつ、独自の固有のフィールドを持っている場合に便利です。
例えば、ユーザープロファイルだけでなく管理者プロファイルも持っている場合を考えてみます。管理者はユーザーと同じフィールドを全て持っていますが、追加でpermissions
フィールドを持っています。
class AdminProfile(UserProfile):
permissions: list[str]
上記のコードでは、AdminProfile
をUserProfile
のサブクラスとして定義し、追加のpermissions
フィールドを追加しています。これにより、AdminProfile
はUserProfile
の全てのフィールドとpermissions
フィールドを持つことが期待されます。
参考