いろは3010814 views
高校物理160203 views
中学理科1630641 views
Computer368106 views
高校化学2924392 views
世界の国564520 views
ヒストリア290598 views
英語613639 views
高校国語788336 views
LaTeX962153 views
Help
Tools
NewsSpreadsheetCalendarSlidesTier ListPen ToolIllustrationCrayonPixel ArtASCII ArtPerspectiveEndless StairsGraphMind MapER DiagramFamily TreeMemeCurved TextImage EditorMosaicRetro FilterPencil SketchOCR/HighlighterMakeup EditorFaviconVideo TrimmerScrolling VideoVideo TitleColor PickerColor ExtractorBonfireFireworksWater RippleWater SplashBreaking GlassWood GrainMarble TextureCSS ButtonIcon MakerBar ChartGrouped Bar ChartStacked Bar ChartPie ChartLine ChartArea ChartStacked Area ChartScatter Plot3D Bar Chart3D Pie ChartBar Chart RaceBubble ChartPopulation PyramidPictogramEarningsCandlestick ChartInvestment RiskMortgage SimulatorCalculatorMatrix CalculatorFunction GraphPolynomial ExpansionVenn DiagramField VisualizerRubik's Cube Group TheoryTraveling SalesmanVoronoi and DelaunayFractalColumn ArithmeticDraw Math FiguresArithmetic AnimationArithmetic Word ProblemsCounting with Tree DiagramsCube NetsCross SectionsMotion PathMechanicsWavesLight and LensesThermodynamicsHow Semiconductors WorkMolecular StructuresAtomic OrbitalsElectrochemical CellsChemical EquilibriumCrystal LatticesBuffer pHComplex IonsDNA Double HelixCell DivisionMembrane ChannelsNerve ImpulseRock ClassificationWeatherConstellationsSolar and Lunar Eclipses3D ModelingFloor PlanSeismic StructuresIntersection TurnMaglevCooking AnimationOrigamiLive Viewer CountGeoJSON MapRailway MapPopulation MapCrime MapLand Price MapSchool MapShrine and Castle MapHouse of Representatives MapWord MapSolitaireReversiHakoiri MusumeChessHamburgerRippleSlide Puzzle MakerNeon PinballNovel MakerJapanese Typing PracticePiano Score EditorMusic Theory

English

Callable — 関数の型ヒント

Python では関数もオブジェクトであり、変数に代入したり他の関数に渡したりできる。こうした「関数を値として扱う」場面で型ヒントを付けるには Callable を使う。引数の型と戻り値の型を明示することで、コールバックやデコレータのシグネチャを正確に表現できるようになる。

Callable の基本構文

Callable は collections.abc モジュールからインポートして使う。

from collections.abc import Callable

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

def add(x: int, y: int) -> int:
    return x + y

result = apply(add, 3, 5)  # 8

Callable[[int, int], int] は「int を 2 つ受け取り、int を返す関数」を意味する。最初のリストが引数の型、リストの外が戻り値の型だ。

Python 3.8 以前では typing.Callable を使う必要があったが、3.9 以降は collections.abc.Callable が推奨されている。古いコードでは from typing import Callable と書かれていることも多いが、collections.abc.Callableのほうが現在の標準である。

typing.Callable は将来的に非推奨となる可能性がある。

引数なしの関数

引数を取らない関数は、空のリストで表現する。

from collections.abc import Callable

def run_task(task: Callable[[], str]) -> str:
    return task()

def greeting() -> str:
    return "Hello!"

print(run_task(greeting))  # Hello!

Callable[[], str] が「引数なしで str を返す関数」を意味する。リストの中身が空であることに注意しよう。

戻り値が None の関数

副作用だけを持つ関数には、戻り値に None を指定する。

from collections.abc import Callable

def on_click(handler: Callable[[str], None]) -> None:
    handler("button_1")

def log_click(element_id: str) -> None:
    print(f"Clicked: {element_id}")

on_click(log_click)

イベントハンドラやログ関数のように「何かを実行するが値は返さない」パターンでよく使う形だ。

実用例:ソート関数のキー

標準ライブラリの sorted が受け取る key 引数も Callable で型を付けられる。

from collections.abc import Callable

def sort_by(items: list[str], key: Callable[[str], int]) -> list[str]:
    return sorted(items, key=key)

words = ["banana", "apple", "fig"]
result = sort_by(words, key=len)  # ["fig", "apple", "banana"]

key: Callable[[str], int] は「文字列を受け取って整数を返す関数」だ。len はまさにこのシグネチャに合致するので、そのまま渡せる。

高階関数とデコレータ

関数を返す関数にも Callable は使える。デコレータを型付けする典型的なパターンを見てみよう。

from collections.abc import Callable
from functools import wraps
import time

def timer(func: Callable[..., float]) -> Callable[..., float]:
    @wraps(func)
    def wrapper(*args: object, **kwargs: object) -> float:
        start = time.time()
        result = func(*args, **kwargs)
        print(f"{func.__name__}: {time.time() - start:.3f}s")
        return result
    return wrapper

@timer
def compute(n: int) -> float:
    return sum(range(n)) * 1.0

Callable[..., float]...(Ellipsis)は「任意の引数を受け取る」ことを示す。引数の型を厳密に指定できない場合に使う記法で、デコレータのように汎用的な関数を包むときに便利だ。

引数を明示

Callable[[int, str], bool] — 引数の型と個数が固定の場合。型チェックが厳密に効く。

Ellipsis を使用

Callable[..., bool] — 引数の型を問わない場合。柔軟だが型チェックは緩くなる。

ParamSpec でデコレータを正確に型付けする

Callable[..., T] は便利だが、元の関数のシグネチャが失われてしまう。Python 3.10 で導入された ParamSpec を使えば、引数の型情報を保持したままデコレータを定義できる。

from collections.abc import Callable
from typing import ParamSpec, TypeVar
from functools import wraps

P = ParamSpec("P")
T = TypeVar("T")

def retry(func: Callable[P, T]) -> Callable[P, T]:
    @wraps(func)
    def wrapper(*args: P.args, **kwargs: P.kwargs) -> T:
        for _ in range(3):
            try:
                return func(*args, **kwargs)
            except Exception:
                continue
        raise RuntimeError("retries exhausted")
    return wrapper

@retry
def fetch(url: str, timeout: int = 30) -> str:
    ...

ParamSpec("P") が元の関数の引数情報をまるごと保持する。これにより、デコレータを通しても fetch の引数の型ヒントが正しく維持される。mypy や IDE の補完もきちんと動く。

TypeAlias と組み合わせる

Callable の型が長くなる場合は、前の記事で紹介した TypeAlias と組み合わせると読みやすくなる。

from collections.abc import Callable
from typing import TypeAlias

EventHandler: TypeAlias = Callable[[str, dict[str, object]], None]
Middleware: TypeAlias = Callable[[dict[str, object]], dict[str, object]]

def register_handler(event: str, handler: EventHandler) -> None:
    ...

def add_middleware(mw: Middleware) -> None:
    ...
Callable は関数の型を表す

引数の型リストと戻り値の型で関数のシグネチャを記述する。コールバックや高階関数に不可欠。

ParamSpec で引数情報を保持

デコレータなど、関数を包む関数で元のシグネチャを維持したいときに使う。Python 3.10 以降で利用可能。

関数を値として受け渡す場面は、イベント処理、プラグインシステム、テストのモック、非同期タスクの登録など多岐にわたる。Callable で型を明示しておけば、渡す関数のシグネチャが合っているかを実行前に検証でき、バグの早期発見につながる。