記事一覧へ戻る 本の順番で続きを読む

型ヒントと静的解析 - 安全なコードを書く

Python3中級 | 2026/02/18 15:44

型ヒントと静的解析

基本の型ヒント

# 変数の型ヒント
name: str = "太郎"
age: int = 25
pi: float = 3.14
is_active: bool = True

# 関数の型ヒント
def greet(name: str) -> str:
    return f"こんにちは、{name}さん"

def add(a: int, b: int) -> int:
    return a + b

コレクションの型ヒント

# Python 3.9+ はビルトイン型を直接使える
names: list[str] = ["太郎", "花子"]
scores: dict[str, int] = {"数学": 85, "英語": 72}
coordinates: tuple[float, float] = (35.68, 139.69)
unique_ids: set[int] = {1, 2, 3}

# ネスト
matrix: list[list[int]] = [[1, 2], [3, 4]]
users: list[dict[str, str]] = [{"name": "太郎"}]

Optional と Union

from typing import Optional

def find_user(user_id: int) -> Optional[dict]:
    """ユーザーが見つからない場合はNoneを返す"""
    if user_id == 1:
        return {"name": "太郎"}
    return None

# Python 3.10+ の新記法
def find_user_new(user_id: int) -> dict | None:
    pass

# Union
def process(data: str | bytes | int) -> str:
    return str(data)

TypedDict

from typing import TypedDict

class UserDict(TypedDict):
    name: str
    age: int
    email: str

def create_user(data: UserDict) -> None:
    print(f"ユーザー作成: {data['name']}")

# 型チェッカーがキーの存在と型を検証
user: UserDict = {"name": "太郎", "age": 25, "email": "taro@example.com"}

Protocol(構造的部分型)

from typing import Protocol

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

class Circle:
    def draw(self) -> None:
        print("円を描画")

class Square:
    def draw(self) -> None:
        print("四角を描画")

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

render(Circle())   # OK: drawメソッドを持つ
render(Square())   # OK: drawメソッドを持つ

mypy による静的型チェック

# インストール
pip install mypy

# 型チェック実行
mypy my_module.py
mypy --strict my_module.py  # 厳格モード
# mypy が検出するエラーの例
def add(a: int, b: int) -> int:
    return a + b

result: str = add(1, 2)  # error: Incompatible types

まとめ

  • 型ヒントはドキュメンテーションとして機能する
  • Optional[X]X | None と同義
  • TypedDict で辞書の構造を定義
  • Protocol でダックタイピングに型安全性を追加
  • mypy で型の整合性を自動検証