一歩​進んだ​型ヒントの​活用​(LT版)

2026/02/21 Ryuji Tsutsui

PyCon mini Shizuoka 2026 LT

Creative Commons License This work is licensed under a Creative Commons Attribution 4.0 International License .

はじめに

自己紹介

  • Ryuji Tsutsui@ryu22e

  • さくらインターネット株式会社所属

  • Python歴は​14年くらい​(主に​Django)

  • 神奈川県横浜市在住

  • 著書​(共著)​:

【PR】3月16日『Python実践レシピ』第2版が​出ます!

最新の​Python 3.14に​対応、​書き下ろし​(uv、​Ruff、​HTTPXなど)​多数!

Amazonのページ

3月16日発売!​(QRコードは​次の​スライド)

【PR】3月16日『Python実践レシピ』第2版が​出ます!

https://amzn.asia/d/0jaaWbIX

Amazon URLのQRコード

3月16日発売!​(予約受付中)

assert_never()関数の​話

Python 3.11で​typingモジュールに​追加された​assert_never()関数を​使うと、​ if文や​パターンマッチの​条件指定漏れを​型チェッカーで​検出できて​便利!と​いう​話を​します​(『Python実践レシピ』第2版の​内容が​元ネタです)。

まず、​こんな​列挙型を​定義する

    """assert_never_example.py"""
    import enum

    class Color(enum.Enum):
        """色の種類"""
        RED = 0
        BLUE = 1
        YELLOW = 2

Colorを​パターンマッチで​判定する​コードを​書く

    # (省略)
    def get_color_name_jp(color: Color) -> str:
        """引数の値に応じて日本語の色名を返す"""
        match color:
            case Color.RED:
                return "赤"
            case Color.BLUE:
                return "青"
            # Color.YELLOWを書き忘れている
            case _:
                return "不明"

    print(get_color_name_jp(Color.RED))  # 「赤」
    print(get_color_name_jp(Color.BLUE))  # 「青」
    print(get_color_name_jp(Color.YELLOW))  # 「黄」ではなく「不明」

assert_never_example.pyの​実行結果

「黄」が​出力されない。

    % python assert_never_example.py
    赤
    青
    不明

テストを​書けば​気付ける​問題だけど……

  • テストケースは​人間が​考える​もの

  • うっかり​テストケースを​書き忘れる​こともある

こんな​時便利なのが​assert_never()関数

    from typing import assert_never  # (1)これを追加

    # (省略)
    def get_color_name_jp(color: Color) -> str:
        match color:
            case Color.RED:
                return "赤"
            case Color.BLUE:
                return "青"
            # Color.YELLOWを書き忘れている
            case _:
                assert_never(color)  # (2)ここを変更

    # (省略)

型チェッカーが​条件指定漏れを​検出してくれる

型チェッカーが​「引数が​Color.YELLOWの​場合に​assert_never()関数が​呼ばれるよ」と​教えてくれる。

    % mypy assert_never_example.py
    assert_never_example.py:17: error: Argument 1 to "assert_never" has incompatible type "Literal[Color.YELLOW]"; expected "Never"  [arg-type]
    Found 1 error in 1 file (checked 1 source file)

この​コードを​実行すると​どうなるか?

assert_never()関数が​AssertionErrorを​送出する。

    % python assert_never_example.py
    赤
    青
    Traceback (most recent call last):
    File "/***/assert_never_example.py", line 21, in 
        print(get_color_name_jp(Color.YELLOW))
            ~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^
    File "/***/assert_never_example.py", line 17, in get_color_name_jp
        assert_never(color)  # ここを変更
        ~~~~~~~~~~~~^^^^^^^
    File "/***/typing.py", line 2582, in assert_never
        raise AssertionError(f"Expected code to be unreachable, but got: {value}")
    AssertionError: Expected code to be unreachable, but got: 

Q. そも​そも、​条件指定漏れの​検出って​「型チェック」なの?

  • A. はい、​型チェックです

  • これを​説明する​ため、​assert_never()関数の​定義を​見てみましょう

assert_never()関数の​ソースコード

引数が​Never型、と​いうのが​ポイント。

def assert_never(arg: Never, /) -> Never:
    value = repr(arg)
    if len(value) > _ASSERT_NEVER_REPR_MAX_LENGTH:
        value = value[:_ASSERT_NEVER_REPR_MAX_LENGTH] + '...'
    raise AssertionError(f"Expected code to be unreachable, but got: {value}")

assert_never()関数と​同じ​機能の​関数を​自作する

assert_never()関数と​同じく、​引数が​Never型の​関数を​定義すれば​よい。

    from typing import Never

    class UnreachableError(Exception):
        pass

    # ↓引数の型をNeverにする
    def assert_unreachable(arg: Never, /) -> Never:
        raise UnreachableError(arg)

Never型って​何?

  • Never型は​「ボトム型」

  • ボトム型とは、​型理論や​数理論理学に​おいて​値を​持たない​型の​こと

  • ざっくり説明すると、​「どんな​値を​入れても​型チェックで​エラーに​なる型」

  • どんな​値を​入れても​エラーに​ならない​Any型の​逆バージョンみたいな​イメージ

以下は​すべて​型チェックで​エラーに​なる

    """never_example.py"""
    from typing import Never
    a: Never = 1  # NG
    b: Never = "test"  # NG
    c: Never = True  # NG
    d: Never = None  # NG

前述の​コードを​型チェック

    % mypy never_example.py
    never_example.py:3: error: Incompatible types in assignment (expression has type "int", variable has type "Never")  [assignment]
    never_example.py:4: error: Incompatible types in assignment (expression has type "str", variable has type "Never")  [assignment]
    never_example.py:5: error: Incompatible types in assignment (expression has type "bool", variable has type "Never")  [assignment]
    never_example.py:6: error: Incompatible types in assignment (expression has type "None", variable has type "Never")  [assignment]

条件指定漏れチェックの​流れ

Never型の​特徴を​利用して、​条件指定漏れチェックを​行っている。

    # (省略)
    def get_color_name_jp(color: Color) -> str:
        match color:
            case Color.RED:
                return "赤"
            case Color.BLUE:
                return "青"
            case _:
                # (1)型チェッカーは引数がColor.YELLOWならここを通ることを
                # 検出
                # (2)引数に指定されているNever型は何を渡しても型エラーに
                # なるので、必ず「assert_never()が呼ばれる=型エラー」になる
                assert_never(color)
    # (省略)

最後に

まとめ

  • assert_never()関数は、​条件指定漏れを​検出してくれる​便利関数

  • この機能は、​引数に​指定された​Never型の​特徴を​利用した​型チェックに​より​実現している

ご清聴​ありがとう​ございました

https://amzn.asia/d/0jaaWbIX

Amazon URLのQRコード

『Python実践レシピ』第2版 3月16日発売、​予約してね!