Categories: Python

【Python】型ヒントで使用する型を指定しよう【アノテーション】

この記事では、Pythonで型ヒントを付ける方法を解説します。

型ヒントを付けることでオブジェクトがなんの型の値を使用するかわかるようになり、異なる型の値を渡す危険性が少なくなります。

また、mypyモジュールを使うことで型ヒントに沿ったソースコードが書けているかどうかをチェックすることができます。

型ヒントに沿ってソースコードが書けているかチェックする方法

それでは、型ヒントの使い方を見ていきましょう!

型ヒントの書き方

型ヒントとは、アノテーションを使って変数や引数に使用する値の型を記述することを言います。Python 3.6で追加されました。

変数の型ヒント

変数には、以下のように型ヒントを書くことができます。

変数名: 型名
変数名: 型名 = 値

型ヒントを書く際に変数を初期化する必要はないが、初期化されていない変数を使うとNameErrorとなるので注意してください。

num: int
print(num)

実行結果

Traceback (most recent call last):
  File "main.py", line 2, in 
    print(num)
NameError: name 'num' is not defined

関数の型ヒント

関数やメソッドには、以下のように型ヒントを書くことができる。

def 関数名(引数名: 型名) -> 戻り値の型名:
    # なんらかの処理

引数にint型の値を2つ取り、戻り値にfloat型の値を返す関数は以下のような感じ。

def func(a: int, b: int) -> float:
    return a / b

戻り値を返さない関数は、型ヒントにNoneを渡しておきます。

def func(a: int, b: int) -> None:
    print(a / b)

デフォルト値を指定する場合は、アノテーションを書いてからデフォルト値を書きます。

def func(a: int = 1, b: int = 2) -> None:
    print(a / b)

特殊な型を指定する

リストの要素の型を指定する場合や辞書のkeyvalueの型を指定したい時は、typingモジュールを使います。

typingモジュールは、Python 3.5で追加された標準モジュールです。

リスト

要素の型を指定したリストの型ヒントを記述するには、typing.Listを使います。Listでは、複数の型を指定することはできません。

from typing import List

List[型名]

int型の要素を格納したリストは以下のような感じ。

from typing import List

values: List[int] = [1, 2, 3]

Python 3.9からはlistで同じことができるようになったのでListは非推奨。

values: list[int] = [1, 2, 3]

タプル

要素の型を指定したタプルの型ヒントを記述するには、typing.Tupleを使います。リストと異なり、格納する要素の数だけ型を記述します。

from typing import Tuple

Tuple[型名, 型名, ...]

int型とstr型の要素を持ったタプルは以下のような感じ。

from typing import Tuple

values: Tuple[int, str] = (1, 'abc')

Python 3.9からはtupleで同じことができるようになったのでTupleは非推奨。

values: tuple[int, str] = (1, 'abc')

辞書

keyvalueの型を指定した辞書の型ヒントを記述するには、typing.Dictを使います。型をコロン(:)ではなくカンマ(,)で区切っているのに注意しましょう。

from typing import Dict

Dict[型名, 型名]

keystr型、valueint型を格納する辞書を指定するには以下のような感じ。

from typing import Dict

values: Dict[str, int]

Python 3.9からはdictで同じことができるようになったのでDictは非推奨。

values: dict[str, int]

ダックタイプ

シーケンスやイテラブルなど複数の型が所属する型を指定することもできます。

from typing import Iterable, Sequence

# イテラブル
Iterable[型名]

# シーケンス
Sequence[型名]

シーケンスの型ヒントを指定している変数をリストで初期化してみます。

from typing import Sequence

values: Sequence[int] = [1, 2, 3]

Python 3.9からはcollections.abc.Sequencecollections.abc.Iterableで同じことができるようになったので非推奨。

from collections.abc import Sequence, Iterable

values: Sequence[int]
values: Iterable[int]

ユニオン

Unionを使うことで複数の型を指定することができます。

from typing import Union

Union[型名, 型名, ..., 型名]

例えば、int型とfloat型の型ヒントは以下のようになります。

from typing import Union

num: Union[int, float] = 3.14

Python 3.10からは|を使って以下のように指定できるようになりました。

# Union[int, float]と同等
num: int | float = 3.14

ジェネレータ

ジェネレータの型ヒントを指定するには、typing.Generatorを使います。

from typing import Generator

Generator[YieldType, SendType, ReturnType]

YieldTypeyieldで返す値の型、SendTypesend()で渡される値の型、ReturnTypereturnで返される値の型を指定します。

そもそもジェネレータの使い方がわからんって方は以下の記事を参考にしてください。

Linkジェネレータの定義と使い方

例として適当なジェネレータに型ヒントを指定してみます:

from typing import Generator

def gen() -> Generator[int, int, int]:
    #  YieldType では int を返している
    yield 1
    # SendType は int を想定している
    val = yield 2
    if val is None or val 

値をsend()で渡さなかったり、returnで値を返さない場合はNoneを指定する。また、YieldTypeのみの場合はIterable[YieldType]Iterator[YieldType]で指定してもよい。

from typing import Generator

def gen() -> Generator[int, None, None]:
    yield 1


from collections.abc import Iterable

def gen() -> Iterable[int]:
    yield 1

Python 3.9からはcollections.abc.Generatorで同じことができるようになったのでtyping.Generatorは非推奨となった。また、以下のように使用しないTypeの型を省略してもTypeErrorが発生しないようになりました。

from collections.abc import Generator

def gen() -> Generator[int]:
    yield 1

さらに複雑な型ヒント

型ヒント中に型ヒントを記述することでさらに複雑な型ヒントを指定できます。

以下のコードでは、keyに文字列、valueに整数を持つ辞書型の型ヒントdataを生成し、dataを要素として持つリスト型の型ヒントdatasを生成しています。

data = dict[str, int]
datas = list[data]

このdatasを変数に定義することで複雑な型ヒントを指定することができます。

data = dict[str, int]
datas = list[data]

vals: datas = [{'a': 1}, {'b': 2}]

他にもいろんな書き方が用意されているので公式サイトを参考にしてください。

まとめ

この記事では、型ヒントの書き方を解説しました。

型ヒントを書くことでソースコードの安全性や可読性が増します。ちょこっとめんどくさいですが毎回書くように心がけましょう!

型ヒントを書いたらmypyモジュールを使ってチェックしてみてください。

型ヒントに沿ってソースコードが書けているかチェックする方法

それでは今回の内容はここまでです。ではまたどこかで〜( ・∀・)ノ

ゆうまる

独学でプログラミングを勉強しているおじさん。いろんな言語を勉強したが浅く広くなためあまり仕事につながらない。また忘れっぽいため自分のブログを備忘録としても使っている。産まれてこのかたずっとネコを飼ってる生粋のネコ派。最近お腹が出てきて筋トレに奮闘中!

View Comments

Recent Posts

【Dart】コンストラクタのデフォルト引数について

Dartのコンストラクタのデフォルト引数…

2週間 ago

【Unity】有料アセットを無料で手に入れる方法

この記事では、Unityの有料アセットを…

4か月 ago

【Python】任意の秒数だけ処理を一時停止する方法【sleep()関数】

この記事では、Pythonで任意の秒数だ…

1年 ago

【Python】Wordの文書の新規作成と読み書き

この記事では、Pythonを使ってWor…

1年 ago

【Python】メタクラスって結局なんなの?

この記事では、Pythonのメタクラスに…

1年 ago