Python型ヒント完全ガイド:typingとmypyで静的解析・バグ防止・可読性向上

Pythonの型ヒント(型アノテーション)の基本からtypingモジュールの高度な型、mypyによる静的解析までを解説。コードのバグ防止と可読性向上に役立つ実践的なテクニックを紹介。

Python型ヒントmypy静的解析バグ防止可読性2026/5/25

Python型ヒントとは?

Python 3.5以降で導入された型ヒント(Type Hints)は、変数や関数の引数・戻り値に期待される型を明示するための文法です。動的型付け言語であるPythonに静的型付けの利点をもたらし、コードの可読性向上やバグの早期発見に貢献します。

基本的な書き方

def greet(name: str) -> str:
    return f"Hello, {name}"

name: str は引数nameがstr型であることを示し、-> str は戻り値がstr型であることを示します。これらのアノテーションは実行時には強制されず、あくまで開発者やツールへのヒントとして機能します。

typingモジュールの主要な型

typing モジュールを使うことで、より複雑な型を表現できます。

基本的な型エイリアス

  • List[int]:整数のリスト
  • Dict[str, float]:キーがstr、値がfloatの辞書
  • Tuple[int, str, float]:3要素のタプル
  • Set[bytes]:バイト列のセット
  • OptionalとUnion

    from typing import Optional, Union
    

    def find_user(user_id: int) -> Optional[dict]: # ユーザーが見つからない場合はNoneを返す ...

    def process(value: Union[int, str]) -> None: print(value)

    Optional[X]Union[X, None] の省略形で、値がX型またはNoneであることを示します。

    AnyとTypeVar

    from typing import Any, TypeVar
    

    T = TypeVar('T')

    def first(items: list[T]) -> T: return items[0]

    Any は任意の型を許容し、TypeVar はジェネリックな型変数を定義します。

    CallableとLiteral

    from typing import Callable, Literal
    

    def apply(func: Callable[[int, int], int], a: int, b: int) -> int: return func(a, b)

    def set_mode(mode: Literal['read', 'write']) -> None: pass

    Callable[[Arg1Type, Arg2Type], ReturnType] で関数の型を、Literal で特定のリテラル値のみを許容します。

    mypyによる静的解析

    mypyはPythonの静的型チェッカーです。型ヒントを解析し、型の不一致を検出します。

    インストールと基本的な使い方

    pip install mypy
    mypy my_script.py
    

    設定ファイル(mypy.ini)

    [mypy]
    python_version = 3.10
    strict_optional = True
    warn_unused_ignores = True
    ignore_missing_imports = True
    

    実践的なチェック例

    <h1>sample.py</h1>
    def add(a: int, b: int) -> int:
        return a + b
    

    result = add(1, "2") # mypyがエラーを報告

    実行結果:

    sample.py:4: error: Argument 2 to "add" has incompatible type "str"; expected "int"
    Found 1 error in 1 file (checked 1 source file)
    

    型ヒントのベストプラクティス

    1. 公開APIには必ず型ヒントを付ける

    ライブラリやモジュールの公開関数・クラスには型ヒントを付けることで、利用者が正しく使えるようになります。

    2. 複雑な型はエイリアスを定義する

    from typing import Dict, List, Tuple
    

    UserData = Dict[str, Union[str, int]] UserList = List[UserData]

    3. プロトコルで構造的サブタイピング

    from typing import Protocol
    

    class Drawable(Protocol): def draw(self) -> None: ...

    def render(obj: Drawable) -> None: obj.draw()

    4. 過剰な型付けを避ける

    全ての変数に型を書く必要はありません。複雑な内部処理では型推論に任せ、境界部分で明示するのが良いバランスです。

    5. サードパーティライブラリの型スタブ

    typeshedtypes-* パッケージを活用し、外部ライブラリの型情報を補完します。

    pip install types-requests types-PyYAML
    

    型ヒントによるバグ防止の実例

    ケース1: Noneチェックの漏れ

    from typing import Optional
    

    def get_name(user: Optional[dict]) -> str: return user["name"] # mypyがエラー: userはNoneの可能性

    修正:

    def get_name(user: Optional[dict]) -> str:
        if user is None:
            return "Guest"
        return user["name"]
    

    ケース2: 引数の型誤り

    def calculate_discount(price: float, rate: float) -> float:
        return price * rate
    

    <h1>誤った呼び出し</h1> discount = calculate_discount(100, "0.1") # 実行時エラー

    mypyが事前に型不一致を検出します。

    高度な型ヒントの活用

    ジェネリクスとTypeVar

    from typing import TypeVar, Generic
    

    T = TypeVar('T')

    class Stack(Generic[T]): def __init__(self) -> None: self.items: list[T] = [] def push(self, item: T) -> None: self.items.append(item) def pop(self) -> T: return self.items.pop()

    オーバーロード

    from typing import overload
    

    @overload def process(data: int) -> str: ... @overload def process(data: str) -> int: ... def process(data): if isinstance(data, int): return str(data) else: return len(data)

    型ガード

    def is_str_list(val: list[object]) -> bool:
        return all(isinstance(x, str) for x in val)
    

    まとめ

    Pythonの型ヒントは、コードの品質を高め、バグを減らし、チーム開発でのコミュニケーションを円滑にする強力なツールです。typingモジュールとmypyを組み合わせることで、動的言語の柔軟性を保ちながら静的型付けの恩恵を受けられます。

    まずは簡単な関数から型ヒントを導入し、徐々にプロジェクト全体に拡大することをおすすめします。特に公開APIや複雑なロジックには積極的に型を付け、mypyのチェックをCIに組み込むと効果的です。

    型ヒントは実行時パフォーマンスに影響を与えず、あくまで開発時の補助ツールです。Pythonの「書きやすさ」を損なうことなく、「読みやすさ」と「信頼性」を向上させるために、ぜひ活用してみてください。