お悩み女子コードの中に name: str とか -> int とか書いてあるけど、これは何のために付いているの?
型ヒントは変数や関数の引数・戻り値に「ここにはこの種類の値が入る予定です」と書き添える仕組みです。数か月後に自分や同僚がスクリプトを読み返したとき、何を渡して何が返ってくるのかがひと目で分かります。
型ヒントの書き方と、業務スクリプトで間違いを見つけるチェック方法を、動くコードつきで紹介します。載せているコードはWindows 11 と Python 3.12 で動くことを確かめています。チェックには mypy(型ヒントの書き間違いを実行前に見つけるツール)を使い、確かめたバージョンは 2.4.0 です。
- 型ヒントの書き方(引数・戻り値・変数)
- 業務スクリプトでよく使う型と、None が返る関数の書き方
- 型ヒントは実行時に守られない、という事実
- mypy で書き間違いを実行前に見つける手順
- 売上CSVの集計コードに型ヒントを付ける例
Pythonの型ヒントの仕組み
型ヒント(タイプヒント)を支える typing モジュールは、Python 3.5 で加わりました。公式の用語集では変数・クラス属性・関数の引数や戻り値について、期待される型を指定する注釈と説明されています。まずは書き方を見てみます。
def format_amount(amount: int) -> str:
return f"{amount:,}円"
store_name: str = "東京店"
print(store_name, format_amount(1234567))
実行結果は次のとおりです。
東京店 1,234,567円
引数の名前の後ろに「: int」と書くと、amount には整数が入る予定、という意味になります。関数の定義の最後に「-> str」と書くと、文字列を返す予定、という意味です。変数も同じ形で、store_name: str = "東京店" のように名前の後ろに型を書きます。
型ヒントは Python の標準の書き方で、追加のインストールは要りません。書いておくと、次の3つで役に立ちます。
- 読む人への説明になる。関数の中身を読まなくても、渡すものと返るものが分かる
- チェックツールが間違いを見つけられる。実行する前に、型の食い違いを指摘してくれる
- エディタの補完が効きやすくなる。公式の用語集にもIDE のコード補完を助ける、と書かれている
型ヒントの書き方|業務スクリプトでよく使う型8つ
業務の自動化で出番が多いのは、文字・数・True/False・リスト・辞書・ファイルの場所・値なしを表す型です。先に一覧を見て、あとで1つずつ書き方を確かめます。
| 書き方 | 意味 | 業務での例 |
|---|---|---|
| str | 文字列 | 店舗名、ファイル名 |
| int | 整数 | 金額、件数 |
| float | 小数 | 平均、割合 |
| bool | True か False | 処理済みかどうか |
| list[str] | 文字列が並んだリスト | 店舗名の一覧 |
| dict[str, int] | キーが文字列、値が整数の辞書 | 店舗ごとの売上 |
| Path | ファイルやフォルダの場所(pathlib) | 読み込むCSVの場所 |
| int | None | 整数、または None(値なし) | 見つからなければ None を返す関数 |
文字・数・True/Falseの型
str・int・float・bool は、そのまま型の名前として書けます。変数に付けるときは、名前の後ろに「: 型」を置きます。
store: str = "東京店"
count: int = 3
names: list[str] = ["東京", "大阪", "名古屋"]
sales: dict[str, int] = {"東京": 120000, "大阪": 98000}
memo: str | None = None
リストと辞書の中身の型
リストと辞書は、角括弧の中に中身の型を書きます。list[str] は文字列のリスト、dict[str, int] はキーが文字列で値が整数の辞書です。
この書き方は Python 3.9 以降で使えます。int | None のように縦線で型をつなぐ書き方は、公式ドキュメントでは Python 3.10 以降とされています。古い Python での書き方は後ほど紹介します。
値がないときのNone
探した値が見つからないときに None(値なし)を返す関数は、業務の自動化でよく書きます。戻り値は int | None のように、整数または None と書きます。
def find_price(prices: dict[str, int], name: str) -> int | None:
return prices.get(name)
print(find_price({"りんご": 120}, "りんご"))
print(find_price({"りんご": 120}, "みかん"))
実行すると、次のように表示されます。
120
None
2行目の None は、辞書に「みかん」がなかったという意味です。戻り値が None になる可能性を型で示しておくと、後のチェックで役に立ちます。
Python実行時の型ヒントの扱い
型ヒントで最初に知っておきたいのは、Python は型ヒントを守らせないという点です。公式ドキュメントには「Python ランタイムは、関数や変数の型アノテーションを強制しません」と書かれています。実際に確かめます。
def double(amount: int) -> int:
return amount * 2
print(double(1500))
print(double("1500"))
出力は次のとおりです。
3000
15001500
2回目は "1500" と引用符で囲んだ文字列を渡していますが、エラーは出ません。文字列に2をかけると同じ文字列を2回つなげる動きになり、15001500 が返ります。
CSV から読み込んだ金額は、そのままだと文字列です。金額を数に直し忘れても、エラーにならないまま計算が進むことがあります。
お悩み女子じゃあ、書いても意味がないんじゃない?
なべくん守らせるのではなく、読んで間違いを探してくれるツールに任せます。次の章の mypy がそれです。
型ヒントのチェック|mypyで実行前に間違いを見つける
mypy はコードを動かさずに、型ヒントと実際の使い方を突き合わせるツールです。
mypyの用意と実行の手順
作業用のフォルダに仮想環境(そのフォルダだけで使うライブラリの置き場)を作り、そこに mypy を入れます。コマンドプロンプトで、次の3行を順に実行します。
py -3.12 -m venv venv
venv\Scripts\python.exe -m pip install mypy
venv\Scripts\python.exe -m mypy check.py
2行目で mypy を入れ、3行目で check.py(さきほどの double 関数のファイル)を調べます。
会社のPCではpip でライブラリを入れてよいかを先に確認してください。仮想環境を使えば Python 本体には手を加えませんが、入れる行為そのものが禁止されている職場もあります。
型の間違いを指摘された例
mypy の出力は次のとおりです。
check.py:6: error: Argument 1 to "double" has incompatible type "str"; expected "int" [arg-type]
Found 1 error in 1 file (checked 1 source file)
読み方は単純です。6行目で、double の1つ目の引数が str(文字列)になっている。期待されているのは int(整数)、という指摘です。
None の扱いも見つけてくれます。find_price 関数の下に、結果へそのまま10を足す2行を書き足して price_check.py として調べます。
price = find_price({"りんご": 120}, "みかん")
print(price + 10)
price_check.py:6: error: Unsupported operand types for + ("None" and "int") [operator]
price_check.py:6: note: Left operand is of type "int | None"
Found 1 error in 1 file (checked 1 source file)
None に足し算はできないという指摘です。動かすと TypeError で止まります。if price is not None: で None かどうかを先に調べる形に直すと、指摘は消えます。
注意点もあります。公式ドキュメントによると、mypy は型ヒントのない関数を既定ではチェックしません。上の double から型ヒントを外すと mypy は「Success: no issues found」と表示しますが、動かすと TypeError で止まります。チェックしてほしい関数には型ヒントを付けておきます。
型ヒントを業務スクリプトで使う|売上CSVの集計を例に
ここまでの内容を、売上CSVを読んで合計と平均を出すスクリプトで組み合わせます。数か月後に読み返す、同僚に渡すといった場面を想定した書き方です。
売上CSVを集計するコード
読み込むのは、次の3店舗分の売上です。ファイル名は sales.csv とします。
店舗,金額
東京,120000
大阪,98000
名古屋,75000
import csv
from pathlib import Path
def read_sales(path: Path) -> list[dict[str, str]]:
with path.open(encoding="utf-8-sig", newline="") as f:
return list(csv.DictReader(f))
def total_amount(rows: list[dict[str, str]]) -> int:
return sum(int(row["金額"]) for row in rows)
def average_amount(rows: list[dict[str, str]]) -> float:
return total_amount(rows) / len(rows)
rows = read_sales(Path("sales.csv"))
print(f"合計: {total_amount(rows):,}円")
print(f"平均: {average_amount(rows):,.0f}円")
sales_total.py として実行すると、合計と平均が表示されます。
合計: 293,000円
平均: 97,667円
関数ごとに、何を受け取って何を返すかが見えるのがポイントです。read_sales は Path を受け取って文字列の辞書のリストを返し、total_amount はそのリストから整数を、average_amount は小数を返します。CSV の金額は文字列なので、合計の関数の中で int() で数に直しています。
このコードに mypy をかけると、「Success: no issues found in 1 source file」と表示されます。
mypyが見つける2つの書き間違い
わざと2か所を書き換えます。14行目で平均の戻り値を int と書き、18行目で Path ではなく文字列を渡します。
# 14行目: 平均は小数になるのに、戻り値を int と書いた
def average_amount(rows: list[dict[str, str]]) -> int:
# 18行目: Path ではなく文字列を渡した
rows = read_sales("sales.csv")
sales_total.py:15: error: Incompatible return value type (got "float", expected "int") [return-value]
sales_total.py:18: error: Argument 1 to "read_sales" has incompatible type "str"; expected "Path" [arg-type]
Found 2 errors in 1 file (checked 1 source file)
2つとも、動かす前に指摘されます。14行目の間違いは return の行(15行目)で指摘されています。18行目の間違いは実行すると AttributeError: 'str' object has no attribute 'open' で止まります。一方、14行目だけの間違いは実行してもエラーにならず、画面には平均が表示されます。型ヒントだけが食い違っている状態です。
後からコードを直すときの型チェック
スクリプトはCSVの列を増やす、金額を税込にする、関数を別のファイルに移すなど、作った後に手を入れる場面がよくあります。そのたびに mypy をかけると、「戻り値を変えたのに、呼び出す側が古いままだった」といった食い違いを実行前に拾えます。変更の影響が出る場所を機械に探してもらえるのが、自動化コードに型ヒントを付ける一番の理由です。
型ヒントを書く範囲|関数の引数と戻り値から
型ヒントは全部に付けなくても動きます。手間に対して効果が大きい場所から始めるのが、続けやすい進め方です。
最初に付ける場所
筆者なら、まず関数の引数と戻り値に付けます。関数は何を渡して何が返るかの約束事なので、ここが書いてあるだけで、読む人の迷いが減ります。
変数への型ヒントはmemo: str | None = None のように中身がすぐ決まらないときだけで足ります。
生成AIに書かせたコードや、検索で見つけたコードにも、型ヒント付きのものがあります。ヒントがあれば読みやすい反面、書かれた型が実際のデータと合っているかは人が確かめます。たとえば、CSV から読んだ金額に int と書かれていないか、といった点です。
古いコードで見かける書き方
古いコードや解説では、from typing import Dict, Optional のように typing モジュールから型を読み込む書き方が出てきます。Optional[int] は int | None と同じ意味、Dict[str, int] は dict[str, int] と同じ扱いで、Python 3.12 でも動きます。
公式ドキュメントでは、Dict や List は Python 3.9 以降「非推奨のエイリアス」とされていますが、削除の予定は今のところない、とされています(2026年10月時点)。新しく書くなら、短い書き方で足ります。
型ヒントに関するよくある質問
型ヒントについて、よくある疑問をまとめました。
- 型ヒントを書くと、プログラムは速くなりますか?
-
速くなる仕組みではありません。Python は実行時に型ヒントを強制せず、チェックツールやエディタが読むための情報として使います。
- list[str] と書くとエラーになる場合は?
-
古い Python を使っている可能性があります。公式ドキュメントでは、
list[str]のような書き方は Python 3.9 以降とされています。それより前の場合は、from typing import Listを使ってList[str]と書きます。
型ヒントとmypyの役割
型ヒントのポイントを整理します。
型ヒントとは:引数・戻り値・変数に、入る値の種類を書き添える仕組み。
よく使う型:str・int・float・bool・list[str]・dict[str, int]・Path・int | None。
実行時の扱い:Python は型ヒントを守らせない。違う型を渡してもエラーにならない。
チェック方法:mypy を使うと、動かす前に型の食い違いを指摘してくれる。ヒントのない関数は見てもらえない。
書く場所:最初は関数の引数と戻り値から。
まずは、手元のスクリプトにある関数を1つ選んで型ヒントを付け、mypy で Success と出るかを確かめてみてください。
型ヒントと一緒に読むと役立つ記事を紹介します。
- Python例外処理の基本|止まらない自動化にするtry/except
- PythonでCSVを集計する基本|合計・平均・グループ化の最小コード
- pathlib入門|Windowsでも迷いにくいファイルパスの扱い方
参考資料
typing — 型ヒントのサポート | Python 3 ドキュメント
用語集: 型ヒント | Python 3 ドキュメント
PEP 484 Type Hints
Getting started | mypy ドキュメント
