Python typingモジュールとは?型ヒントの書き方を初心者向けに解説
Pythonのtypingモジュールは、変数や関数に「どんな型が入るか」を書き添えるための仕組みです。
書いても実行時の動作は変わりません。代わりに、エディタの補完とエラー検出が効くようになり、型チェッカーがバグを見つけてくれます。
型ヒントは実行時に強制されない
ここを最初に理解しておくと、以降の話が一本の線でつながります。
def greet(name: str) -> str:
return "Hello, " + name
print(greet("佐藤"))
print(greet(123))
実行結果:
Hello, 佐藤
TypeError: can only concatenate str (not "int") to str
エラーは出ましたが、これは型ヒントが止めたのではありません。文字列と数値を+でつなごうとして失敗しただけです。
Pythonはname: strを見ても何もチェックしません。実際、書き込まれるのは辞書1つだけです。
def f(a: int, b: str = "x") -> bool: ...
print(f.__annotations__)
実行結果:
{'a': <class 'int'>, 'b': <class 'str'>, 'return': <class 'bool'>}
では何のために書くのか
価値を生むのは型チェッカーです。代表的なのがmypyで、コードを実行せずに矛盾を見つけます。
# a1.py
def greet(name: str) -> str:
return "Hello, " + name
greet(123)
$ mypy a1.py
a1.py:4: error: Argument 1 to "greet" has incompatible type "int"; expected "str" [arg-type]
実行する前に間違いが分かりました。テストを通さないと気づけなかったバグを、書いた瞬間に潰せます。
| 得られるもの | 内容 |
|---|---|
| 早期のバグ発見 | 実行せずに型の矛盾を検出 |
| エディタの補完 | 変数の型が分かるので候補が出る |
| ドキュメント代わり | 引数と戻り値が読めば分かる |
| 安全な変更 | 型を変えたとき影響箇所が洗い出せる |
基本の書き方
age: int = 28
name: str = "佐藤"
scores: list = []
def add(a: int, b: int) -> int:
return a + b
def show(msg: str) -> None:
print(msg)
- 変数は
変数名: 型 = 値 - 引数は
引数名: 型 - 戻り値は
-> 型 - 何も返さない関数は
-> None
コレクションの中身まで書く
def total(nums: list[int]) -> int:
return sum(nums)
print(total([1, 2, 3]))
実行結果:
6
listだけでは「リストである」としか伝わりません。list[int]と書けば中身が整数だと分かります。
$ mypy a9.py
a9.py:5: error: List item 0 has incompatible type "str"; expected "int" [list-item]
この書き方はPython 3.9以降で使えます。詳しくは「Python list[int]・dict[str, int]とは?コレクションの型ヒントの書き方」で解説しています。
typingモジュールの主要な型
| 型 | 意味 | 解説記事 |
|---|---|---|
Optional[X] |
XかNone |
Optional |
Union[X, Y] |
XかY | Union |
Any |
どんな型でも | Any |
Literal["r", "w"] |
決まった値だけ | Literal |
TypedDict |
辞書のキーと型を定義 | TypedDict |
Callable[[int], str] |
関数を受け取る | Callable |
バージョンによって書き方が変わる
型ヒントは仕様の変化が速く、ネットの記事が古い書き方のままということがよくあります。
| やりたいこと | 古い書き方 | 新しい書き方 | 使える版 |
|---|---|---|---|
| 整数のリスト | List[int] |
list[int] |
3.9以降 |
| 文字列か数値 | Union[int, str] |
int | str |
3.10以降 |
| Noneを許す | Optional[str] |
str | None |
3.10以降 |
Python 3.9で|を使うとエラーになります。
x = int | str
実行結果(Python 3.9):
TypeError: unsupported operand type(s) for |: 'type' and 'type'
対象とするPythonのバージョンで書き方を決めてください。古い環境も想定するライブラリでは、typingからimportする書き方のほうが安全です。
型チェッカーを導入する
$ pip install mypy
$ mypy your_script.py
いきなり全ファイルに適用するとエラーが大量に出て心が折れます。次の順序がおすすめです。
- 新しく書く関数だけ型ヒントを付ける
- 触ったファイルに少しずつ広げる
- 設定を厳しくしていく(
--strictは最後)
型ヒントは全部書かなくても効果があります。書いた部分だけチェックされ、書いていない部分は素通りするだけです。
どこまで書くべきか
| 場面 | 方針 |
|---|---|
| 使い捨てのスクリプト | 書かなくてよい |
| 他人が使う関数 | 引数と戻り値は書く |
| ライブラリの公開API | 必ず書く |
| チーム開発 | 書く(レビューが楽になる) |
| 関数の中のローカル変数 | 型が明らかなら不要 |
「境界」に書くのが費用対効果が高いと覚えてください。関数の入口と出口が分かれば、中身は読まなくても使えます。
typingモジュールのまとめ
- 型ヒントは実行時に強制されない。
__annotations__に入るだけ - 価値を生むのは型チェッカー(mypy)とエディタの補完
- コレクションは中身まで書く(
list[int]) - 3.9以降は
list[int]、3.10以降はint | str - 全部書かなくてよい。関数の境界から始める



