Yomiage
メニュー

Python実践講座 10:型注釈とProtocolで境界を明確にする

更新 2026/9/27 6:22:11 公開

投稿者: しゅりりん

到達点は、型注釈を実行時検査と混同せず、関数の契約を示すことです。前提は第05・08回です。

型は読み手と検査道具への情報

引数と戻り値へ型を付けると、関数が何を受け取り何を返すかが分かります。mypyなどの静的型チェッカーは実行前に矛盾を探します。一方、JSONやユーザー入力の正しさは、実行時に別途検査する必要があります。

from typing import Protocol


class Sender(Protocol):
    def send(self, message: str) -> None: ...


class Recorder:
    def __init__(self) -> None:
        self.messages: list[str] = []

    def send(self, message: str) -> None:
        self.messages.append(message)


def complete(title: str, sender: Sender) -> None:
    sender.send(f"完了: {title}")


def find_title(titles: dict[int, str], task_id: int) -> str | None:
    return titles.get(task_id)


recorder = Recorder()
complete("型を学ぶ", recorder)
print(recorder.messages)
title = find_title({1: "復習"}, 2)
print("見つかりません" if title is None else title)

main.pyとして実行すると、一件の記録と「見つかりません」が出ます。RecorderはSenderを継承していませんが、必要なsendを持つため構造的に適合します。省略記号はProtocol内の操作の宣言で、業務処理の未実装を隠すためのものではありません。

型を絞ると分岐が見える

str | None は文字列か不在のどちらかです。Noneでないと確認した後なら文字列として扱えます。Anyを多用すると検査を弱めてしまいます。何でも受け取るのではなく、境界で検証した型へ変換して内部へ渡します。

外部入力が辞書なら、TypedDictで期待構造を記述できますが、それだけでは値を実行時に検証しません。型チェッカーの設定と版も開発環境へ記録します。型チェックが通ることと、業務ルールが正しいことは別なので、テストと併用します。

練習と解答

練習:find_titleの結果へ、確認せずupperを呼ぶコードを書き、静的検査で指摘される理由を説明します。

解答:戻り値にはNoneが含まれ、Noneにupperはありません。Noneの分岐を設けるか、見つからなければ例外にする別の契約へ変えます。単にcastで警告を消しても実行時の安全は増えません。

公式資料

typingとmypy公式資料が参照先です。


Python全20回の目次 | 前の回 | 次の回

このブラウザでは Web Speech API が利用できません。

1 / 15 · 停止中