この記事では、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)
特殊な型を指定する
リストの要素の型を指定する場合や辞書のkey
、value
の型を指定したい時は、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')
辞書
key
、value
の型を指定した辞書の型ヒントを記述するには、typing.Dict
を使います。型をコロン(:)ではなくカンマ(,)で区切っているのに注意しましょう。
from typing import Dict
Dict[型名, 型名]
key
にstr
型、value
にint
型を格納する辞書を指定するには以下のような感じ。
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.Sequence
やcollections.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]
YieldType
にyield
で返す値の型、SendType
にsend()
で渡される値の型、ReturnType
にreturn
で返される値の型を指定します。
そもそもジェネレータの使い方がわからんって方は以下の記事を参考にしてください。
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 < 0:
# ReturnType は int を返している
return -1
yield 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
モジュールを使ってチェックしてみてください。
それでは今回の内容はここまでです。ではまたどこかで〜( ・∀・)ノ