LoginSignup
12
9

More than 1 year has passed since last update.

python の TypeVar を最もシンプルな例で理解する

Posted at

python の型ヒント(アノテーション)については、基本的に 公式ドキュメント に記述されている。しかし、実用的な範囲でのシンプルな例が記載されているため、理解したいこと以外の情報もあり、やや理解しにくいことがある。そのため今回、実用性は度外視し、 TypeVar 自体を理解することだけを目的とした情報を残したく、本記事を作成した。なお、記事中の表現は、筆者独自の表現である場合があることはご了承いただきたい。

python のバージョンは 3.9 を想定している。

TypeVar とは

TypeVar とは、「とある決まった型」を表す場合に用いる型変数である。

TypeVar の使用例

例えば下記のように、引数をそのまま返す関数の定義に使用する。

use_typevar.py
from typing import TypeVar

T = TypeVar("T")


def get_t_arg(arg: T) -> T:
    return arg

上記の get_t_arg(arg: T) -> T の型ヒントは、 「引数 arg の型が T であるとき、返り値の型が T である」 ことを意味する。例えば、 get_t_arg の引数として渡した arg の型が int であるときの返り値の型は int であるし、 arg の型が str であるときの返り値の型は str である。

TypeVar と Any の違い

Any とは、制約のない型である。

下記例を用いて TypeVar との違いの説明を試みる。

use_any.py
from typing import Any


def get_any_arg(arg: Any) -> Any:
    return arg

上記の get_any_arg(arg: Any) -> Any の型ヒントは、 「引数 arg に型の制約はなく、返り値にも型の制約はない」 ことを意味する。例えば、 get_any_arg の引数として渡した arg の型が int であるときの返り値の型に制約はなく、返り値の型が intstr などの可能性がある(当然 get_any_arg の実装上、引数と返り値の型が異なることはないが、型ヒントが表すのはそのような意味となる)。

このように、 TypeVarAny は全く異なる。

許容する型を制限する場合の TypeVar の使用例

TypeVar を用いたいが、許容する型を制限したい場合がある(例えば「 int または float のみを許容する」など)。その際の使用例は下記。

use_int_or_float_typevar.py
from typing import TypeVar

T = TypeVar("T", int, float)


def add_one_to_t_arg(arg: T) -> T:
    return arg + 1

上記のように T = TypeVar("T", int, float) と宣言した際の add_one_to_t_arg(arg: T) -> T の型ヒントは、 「引数 arg の型は int または float であり、 arg の型が int のときの返り値の型は intarg の型が float のときの返り値の型は float である」 ことを意味する。

許容する型を制限する場合の TypeVar と Union の違い

Union とは、「指定したいずれかの型」を表す型である。

下記例を用いて TypeVar との違いの説明を試みる。

use_union.py
from typing import Union


def add_one_to_num(num: Union[int, float]) -> Union[int, float]:
    return num + 1

上記の add_one_to_num(num: Union[int, float]) -> Union[int, float] の型ヒントは、 「引数 num の型は int または float であり、返り値の型も int または float である」 ことを意味する。例えば、 add_one_to_num の引数として渡した num の型が int であるとき、返り値の型は int である可能性も float である可能性もある。

複数の TypeVar を使用する例

use_multi_typevar.py
from typing import TypeVar

T = TypeVar("T")
S = TypeVar("S")


def get_t_and_s_args(t_arg: T, s_arg: S) -> tuple[T, S]:
    return t_arg, s_arg

上記の get_t_and_s_args(t_arg: T, s_arg: S) -> tuple[T, S] の型ヒントは、 「第一引数 t_arg の型が T、第二引数 s_arg の方が S のとき、返り値の方は tuple[T, S] である」 ことを意味する。

以上です。閲覧ありがとうございました!

12
9
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
12
9