Pythonの型ヒント(型アノテーション)のすすめ

Python

はじめに

Pythonで開発していると、関数を読んだ時に引数にどういう値が入るか、また戻り値がどういう値になるかわからなくなる場合があります。
そういう時には型ヒント(型アノテーション)が便利です。
mypyなどの静的解析ツールと組み合わせることで型チェックを堅牢にできますが、ここでは型ヒントについてのみ説明します。

def calculate_total(items):
    # itemsがリストかどうか分からない
    # 各要素が数値かどうかも分からない
    return sum(items)

# 実行してみると...
result = calculate_total(["100", "200", "300"])  # 文字列のリスト
print(result)  # "100200300" 文字列が結合される

このような問題は、型ヒントを使うことで防げます。

def calculate_total(items: list[int]) -> int:
    # 型ヒントにより、itemsは整数のリストであることが明確に
    return sum(items)

# mypyが実行前にエラーを検出
result = calculate_total(["100", "200", "300"])  # エラー: 文字列のリストは整数のリストではない

この記事ではPythonの型ヒントの使い方と注意点を紹介します。

型ヒントの使い方

1. 関数の引数や戻り値の型を明示

# 型ヒントなし
def process_user(user):
    return user.get("name")  # userが辞書かどうか分からない

# 型ヒントあり
def process_user(user: dict[str, str]) -> str:
    return user["name"]  # 型が明確なので安全にアクセスできる

2. 変数がNullableかどうか

typing.Optionalという標準ライブラリを使うことで、変数がNoneの値を取る可能性があることを明示できます。

# 型ヒントなし
def get_user_name(user_id):
    if user_id < 0:
        return None
    return f"User{user_id}"

name = get_user_name(-1)
print(name.upper())  # Noneはupperメソッドを持たないのでエラー

# 型ヒントあり
from typing import Optional

def get_user_name(user_id: int) -> Optional[str]:   # Optional[str]はstr型かNone型のどちらかを取ることを示す
    if user_id < 0:
        return None
    return f"User{user_id}"

name = get_user_name(-1)
if name is not None:
    print(name.upper())

3. 変数の宣言時にも型ヒントが使える

単純に変数を宣言・代入する際にも型ヒントを使うことができます。

name: str = "Python"
age: int = 25
height: float = 175.5
is_student: bool = True
array: list[int] = [1, 2, 3]
dict_map: dict[str, int] = {"a": 1, "b": 2, "c": 3}

型ヒントを破るとどうなるか

Pythonの型ヒントは、実行時の動作には影響しません。
つまり、型ヒントと異なる型の値を渡しても、Pythonはそのまま実行します。
「それでは意味がないじゃないか」と感じるかもしれませんが、静的解析で使用される他、可読性という観点でも役に立ちます。
例えばVSCodeなどのIDEでは、型ヒントを使うことで補完や警告を出してくれたりします。

まとめ

型ヒントは、以下のような場面で特に役立ちます:

  1. チーム開発でのコードの理解を助ける
  2. 実行前にバグを発見できる
  3. IDEのコード補完が正確になる
  4. 複雑なデータ構造の型を明確にできる

さらに学びたい方へ

Udemyのこちらの動画が勉強になります。

(Udemy動画は結構高いものもありますが、セールで80%OFFになったりもするので、セールのタイミングで一気に購入してしまうのがおすすめです)

コメント

タイトルとURLをコピーしました