🎀

デコレータ内部構造 — @が実際にやること

関数を受け取って関数を返す関数 — それが全て

@my_decorator
def greet():
    return 'hello'

# 上のコードはこれと完全に同一:
greet = my_decorator(greet)

@は魔法ではない。関数を引数に受け取り新しい関数を返す関数を適用するシンタクティックシュガー。

基本構造

wrapperはクロージャで外部関数の変数(func)をキャプチャ保存。*args, **kwargsで元関数がどんなシグニチャでも受けられる。

functools.wrapsが必要な理由

適用するとgreet.__name__'wrapper'になる。元関数のメタデータ消失。@functools.wraps(func)で元メタデータをコピー。

引数付きデコレータ

3重ネスト。repeat(3)decoratorを返し、decorator(say_hello)wrapperを返す。FastAPIの@app.get('/path')もこのパターン。

キーポイント

1

@decoratorはfunc = decorator(func)のシンタクティックシュガー

2

wrapper関数がクロージャで元funcをキャプチャ

3

functools.wraps(func)で元メタデータ保存必須

4

引数付きデコレータは3重ネスト:outer(args) → decorator(func) → wrapper(*args)

ユースケース

ロギング — 関数呼び出し時点/引数/返却値を自動記録 FastAPI — @app.get("/path")でルーティング登録