Python の overload デコレータで関数をオーバーロードする

typing.overload デコレータを使うと、引数の型によって戻り値の型が変わる関数のオーバーロードを型ヒントで表現できます。

問題の背景

引数の型によって戻り値の型が異なる関数があります。

def process(value):
    if isinstance(value, int):
        return value * 2        # int を返す
    elif isinstance(value, str):
        return value.upper()    # str を返す

単純な型ヒントでは、この関係を正確に表現できません。

overload の使い方

overload デコレータで複数のシグネチャを定義し、最後に実装を書きます。

from typing import overload

@overload
def process(value: int) -> int: ...

@overload
def process(value: str) -> str: ...

def process(value: int | str) -> int | str:
    if isinstance(value, int):
        return value * 2
    else:
        return value.upper()

overload で装飾された関数はスタブであり、実行されません。型チェッカーだけが参照します。実際の実装は最後の関数で行います。

型チェッカーの動作

x = process(10)      # 型チェッカーは x を int と推論
y = process("hello") # 型チェッカーは y を str と推論

overload を使わない場合、戻り値は int | str と推論され、どちらの型かが曖昧になります。

注意点

overload は型チェック専用で、実行時には効果がない
最後の実装関数には overload を付けない
オーバーロードの順序は特殊なものを先に書く

overload を活用すると、複雑な関数でも呼び出し側で正確な型推論が得られます。