TypeVarとは
TypeVar(Type Variable)は、Pythonのtyping
モジュールにある強力な機能で、柔軟性が高く動的な型ヒントを作成できます。これにより、型の安全性を維持しながら汎用的な関数やクラスを作成し、コードの再利用が可能となります。TypeVarは、複数の型で動作する関数やクラスを定義し、それらの型にいくつかの制約を課す必要がある場合に特に有用です。
TypeVarを作成するには、まずtyping
モジュールからインポートする必要があります。
from typing import TypeVar
そして、一意な名前を指定してTypeVarを定義します。
T = TypeVar("T")
この例では、T
は汎用型を表し、TypeVarが使用されたときに任意の型に置換できます。
TypeVarの制約と境界
TypeVarを定義する際に、制約や境界を指定することができます。これにより、TypeVarに代入できる可能性のある型を制限することができます。
制約を設定するには、TypeVarの定義に1つ以上の型を指定します。
U = TypeVar("U", int, float)
この場合、 U
はint
またはfloat
のどちらかに置き換えることができます。
境界を設定するには、 bound
引数を使用します。
from typing import List
V = TypeVar("V", bound=List)
ここでは、 V
はList
のサブクラスである任意の型になります。
汎用関数の型ヒント
汎用関数は、複数の種類の引数で動作する関数で、型の安全性を維持します。汎用関数を作成するには、TypeVarを使用して関数の引数と戻り値の型を表現することができます。
単純な恒等関数の例を紹介します。
def identity(x: T) -> T:
return x
ここでは、 T
は任意の型を表すTypeVarです。恒等関数は、型T
の単一の引数x
を受け取り、同じ型T
の値を返します。
TypeVarを活用した柔軟な型制約
TypeVarを使用して、汎用関数でより複雑で柔軟な型制約を作成することができます。例えば、2つの引数を受け取ってその合計を返す関数を考えてみます。この関数は整数と浮動小数点数の両方で動作する必要がありますが、混在した型では動作しない必要があります。
from typing import TypeVar, Union
Number = TypeVar("Number", int, float)
def add(x: Number, y: Number) -> Number:
return x + y
この例では、TypeVar Number
がint
とfloat
の制約を持って定義されています。 関数add
は、型Number
の2つの引数を取り、同じ型の値を返します。これにより、関数は整数と浮動小数点数の両方で動作することが保証されますが、混在した型では動作しません。
汎用関数でのTypeVarの実践的な例
TypeVarを使用した汎用関数の実践的な例を紹介します。
リスト内のアイテムのインデックスを検索する汎用関数
from typing import List, Optional, TypeVar
T = TypeVar("T")
def find_index(items: List[T], target: T) -> Optional[int]:
for i, item in enumerate(items):
if item == target:
return i
return None
この例では、 find_index
関数は、型T
のアイテムのリストと同じ型T
の目標アイテムを引数に取ります。リスト内で目標アイテムのインデックスを返します。アイテムが見つからない場合は、None
を返します。
2つの辞書をマージする汎用関数
from typing import Dict, TypeVar
K = TypeVar("K")
V = TypeVar("V")
def merge_dicts(dict1: Dict[K, V], dict2: Dict[K, V]) -> Dict[K, V]:
result = dict1.copy()
result.update(dict2)
return result
この例では、 merge_dicts
関数は、キーが型K
で値が型V
の2つの辞書を引数に取ります。両方の入力辞書からキーと値のペアをマージし、新しい辞書を返します。
参考