変数、関数に対する型アノテーション | 型ヒントの導入 | Python本格超入門

スポンサーリンク
スポンサーリンク
amazon
スマイルSALE
--:--:--
ad. 価格範囲を指定して商品を探せます

変数、関数に対する型アノテーション

Pythonは柔軟な動的型付け言語ですが、コードの可読性を高め、型に関するバグを未然に防ぐために型アノテーション(Type Annotation)を利用することができます。アノテーションとは「注釈」という意味であり、変数や関数の引数、戻り値に対して「どのようなデータ型を期待しているか」をソースコードに注釈として刻み込むことができます。このガイドでは、変数や関数に対する具体的な書き方と、実務でよく使う応用的なアノテーションについて解説します。

変数に対する型アノテーション

変数に対する型アノテーションは、その変数がどのようなデータを持つべきかを明示するために使用します。変数名の後ろにコロン : を打ち、続けて型名を記述します。

# 変数に対する型アノテーションの例
name: str = "Alice"
age: int = 25
is_active: bool = True

print(name)       # "Alice"
print(age)        # 25
print(is_active)  # True

この例では、name が文字列(str)、age が整数(int)、is_active がブール型(bool)であることを示しています。

関数に対する型アノテーション

関数に対しても型アノテーションを使うことで、引数や戻り値の型を明示できます。これは、関数がどのような入力を受け取り、どのような結果を出力するのか(関数の仕様書)をコード上で明確にするために非常に有用です。

# 関数に対する型アノテーションの例
def add_numbers(x: int, y: int) -> int:
    return x + y

result = add_numbers(5, 10)
print(result)  # 15

この例では、引数 xy が整数型であり、関数が最終的に返す戻り値(-> の先)も整数型であることが一目で分かります。

複数の引数を持つ関数の型アノテーション

複数の異なる型が混ざる関数であっても、引数ごとに個別にアノテーションを付けることができます。デフォルト値(初期値)を設定する場合の書き方も合わせて押さえておきましょう。

# 複数の引数と、デフォルト値がある場合の型アノテーション
def greet(name: str, age: int, message: str = "Hello") -> str:
    return f"{message}, {name}. You are {age} years old."

# デフォルト値を活かして呼び出し
print(greet("Bob", 30))  # "Hello, Bob. You are 30 years old."

この関数では、name が文字列、age が整数、デフォルト値を持つ message が文字列であり、戻り値が文字列であることを示しています。引数にデフォルト値を指定する場合は、型名 = 値 の順で記述します。

複雑なデータ構造に対する型アノテーション(モダンな書き方)

リストや辞書といった、中に複数の要素を含むコレクション型に対しても詳細にアノテーションを適用できます。過去のPython(3.8以前)では typing モジュールから大文字の ListDict をインポートする必要がありましたが、現在のモダンなPython(3.9以降)では標準の小文字(listdict)をそのまま使用するシンプルな書き方が推奨されています。

# Python 3.9以降の推奨される書き方(標準のコレクション型を使用)
numbers: list[int] = [1, 2, 3, 4, 5]                  # 整数のリスト
students: dict[str, int] = {"Alice": 25, "Bob": 30}   # キーが文字列、値が整数の辞書

print(numbers)   # [1, 2, 3, 4, 5]
print(students)  # {'Alice': 25, 'Bob': 30}

# ※古いPython 3.8以前の環境コードを保守する場合は、以下のように書かれていました
# from typing import List, Dict
# numbers: List[int] = [1, 2, 3, 4, 5]

このように list[int]dict[str, int] と記述することで、データ構造の内側の型までエディタや静的解析ツールに伝えることができます。

一歩進んだ応用:複数の型を許容する(Union / | 演算子)

実務では「整数、または浮動小数点数のどちらを受け取っても良い」というように、複数の型を認めたいケースがあります。モダンなPython(3.10以降)では、パイプ記号 | を使うことで、複数の型をスマートに並べて指定(Union型)することができます。

# int型、またはfloat型を許容するアノテーション(Python 3.10以降)
def process_score(score: int | float) -> str:
    return f"Score: {score}"

print(process_score(95))    # 整数を渡してもOK
print(process_score(88.5))  # 小数を渡してもOK

型アノテーションの注意点と効果的な運用

型アノテーションを導入するにあたり、以下の設計思想を理解しておくことが大切です。

  • 「ヒント」と「アノテーション」の違い: 厳密には、コードに記述された注釈そのものを「アノテーション」、それを利用してエディタやツールに型を伝える仕組み全体を「型ヒント」と呼びますが、実務ではほぼ同じ意味の言葉として使われています。
  • 強制力はない: 何度も強調する通り、Pythonの実行エンジンはアノテーションを完全に無視して動作します。間違った型が渡されても実行時には検知できないため、厳格なチェックには mypy などの外部型チェッカーを開発フロー(CIなど)に組み込む必要があります。
  • 段階的な導入が可能: すべてのコードに書く必要はありません。まずはバグが起きやすい「重要な関数の引数・戻り値」からピンポイントでアノテーションを付けていく、といった柔軟な運用が可能です。

まとめ

型アノテーションは、Pythonならではの「素早く、柔軟にコードが書ける」というメリットを邪魔することなく、チーム開発や大規模化に耐えうる「堅牢さ」をプラスできる優れた仕組みです。特にモダンなPython 3.9以降の組み込み型(list[...])や、Python 3.10以降の | 演算子による複数型指定などを組み合わせることで、非常にスマートで美しいコードを記述できます。関数の入出力を明示する習慣を身につけ、バグの少ないクリーンなPythonコードを目指しましょう。