Python 3.12では、型ヒントに新たな機能が追加されました。特に、PEP 695: 型パラメータ文法は、今後のPythonで広く使われることになるでしょう。

型パラメータ文法

Python3.12では、ジェネリックスを使った型ヒントの書き方に大きな変化がありました。これまで、Pythonの型ヒントはあくまで補助的な機能と位置づけられており、Python3.0で追加されたPEP 3107:関数アノテーションで型ヒントが書けるようになってから、型ヒントを記述するための文法はあまり追加されていませんでした。

しかし、PEP 695: 型パラメータ文法では、Python3.0以来、十数年ぶりに型ヒント用の文法が大きく追加されることになりました。

ジェネリックス

Pythonの型ヒントは、ジェネリックスをサポートしていて、色々なデータ型をサポートする、汎用的なクラスや関数を記述できます。

たとえば、次の関数 get_first はリストから先頭の要素を返します。リストには、整数でも文字列でも、どんな型のデータが入っていてもかまいません。

def get_first(L):
    return L[0]

int_list = [0, 1, 2, 3]
first = get_first(int_list)  # firstの値は0

この関数の型ヒントは、次のようにかけます。ここでは、「 get_first() の仮引数 L は、任意の型 T のオブジェクトを要素とするリストで、戻り値の型は T です」と定義しています。

from typing import TypeVar

T = TypeVar('T')  # 型変数Tの定義

def get_first(L: list[T])->T:
    return L[0]

int_list = [0, 1, 2, 3]  # int_listの型は list[int]
first:int = get_first(int_list)  # firstの値は0

これまで、Pythonでジェネリックスを定義する場合には、この例のように TypeVar オブジェクトを作成して型変数を定義する必要がありました。

Python3.12以降のジェネリックス

PEP 695: 型パラメータ文法では、 TypeVar の定義なしで、直接ジェネリックスを記述できるようになりました。

Python3.12では、上記の get_first() を次のように書けます。

def get_first[T](L: list[T])->T:
    return L[0]

int_list = [0, 1, 2, 3]  # int_listの型は list[int]
first:int = get_first(int_list)  # firstの値は0

型変数は、 def get_first [T] (... のように、関数名に続けて [] の中に記述します。

複数の型変数を要する場合は、次のように記述します。

def make_tuple[T1, T2](a: T1, b: T2)->tuple[T1, T2]:
    return (a, b)

tp = make_tuple(10, "hello")  # tpの型は tuple[int, str]

ジェネリッククラス

これまでジェネリックスを使った汎用的なクラスは、次のように Generic 型を基底クラスとして定義していました。

from typing import TypeVar, Generic

T = TypeVar('T')  # 型変数Tの定義

class Stack(Generic[T]):
    _list: list[T]

    def __init__(self):
        self._list = []

    def push(self, v:T)->None:
        self._list.append(v)

    def pop(self)->T:
        return self._list.pop()

stack = Stack[int]()
stack.push(100)
print(stack.pop())

これも、Python3.12では TypeVarGeneric を使わずに、次のように書けるようになりました。

class Stack[T]:
    _list: list[T]

    def __init__(self):
        self._list = []

    def push(self, v:T)->None:
        self._list.append(v)

    def pop(self)->T:
        return self._list.pop()

新しい記法を利用した場合、基底クラスに Generic がなくとも、自動的に Generic の派生型となります。

以上、Python 3.12の型パラメータ文法についての概要でした。この新機能により、Pythonの型ヒントはより直感的で簡潔に記述できるようになり、Pythonの型システムはさらに強力で使いやすくなりました。

投稿者 admin

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です