Contents
1. 何が変わったか ― 正しい情報だけをまとめる
| 項目 | Python 3.11 以前 | Python 3.12 |
|---|---|---|
| デコレータ構文 | @decorator(名前または属性アクセス)※引数付きは必ず () が必要 |
構文自体に新機能は追加されていません。PEP 614 (Python 3.9) で「任意の式をデコレータとして書ける」ようになったことは既に有効ですが、引数付きデコレータで括弧を省略できるという変更はありません。 |
| 型ヒント支援 | ParamSpec と Concatenate は Python 3.10 から利用可能だが、IDE のサポートがまばら |
静的解析ツールと IDE(pyright, mypy, VS Code 等)が ParamSpec/Concatenate を正式に認識しやすくなり、デコレータのシグネチャを正確に表現できるようになりました。 |
| 標準ライブラリのデコレータ | 従来通り(@functools.lru_cache など) |
functools.cache が Python 3.12 で追加され、シンプルなキャッシュデコレータとして利用可能に。 |
参考情報
- Python 3.12 Release Notes – Decorators(https://docs.python.org/3.12/whatsnew/3.12.html#decorators)
- PEP 614 – “Relaxing Grammar Restrictions on Decorators” (https://peps.python.org/pep-0614/)
誤解しやすい点
- 「引数付きデコレータでも
()を省略できる」 という記述は事実ではありません。PEP 614 は 「任意の式をデコレータに書ける」(例:@my_factory()[0])ことを許可しただけです。 - 括弧省略が正式に導入される予定は Python 3.13 の PEP 695(型パラメータ構文) でも触れられていません。現行の Python 3.12 では必ず
@decorator(arg)の形で記述してください。
2. 実務で活かす ― 型ヒントと標準デコレータを組み合わせたベストプラクティス
2‑1. デコレータのシグネチャを型安全に書く例
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
from __future__ import annotations import functools from typing import Callable, ParamSpec, TypeVar P = ParamSpec('P') R = TypeVar('R') def timer(func: Callable[P, R]) -> Callable[P, R]: """実行時間を測定して標準出力に表示するデコレータ""" @functools.wraps(func) def wrapper(*args: P.args, **kwargs: P.kwargs) -> R: import time start = time.perf_counter() result = func(*args, **kwargs) elapsed = time.perf_counter() - start print(f"[TIME] {func.__name__}: {elapsed:.4f}s") return result return wrapper |
ParamSpecとTypeVarにより、元関数の引数と戻り値型がそのまま保たれます。- 静的解析ツールは
timerが受け取るシグネチャを正しく推論でき、IDE の補完も期待通りに動作します。
2‑2. Python 3.12 で新たに利用可能な標準デコレータ
|
1 2 3 4 5 6 7 8 |
import functools @functools.cache # Python 3.12 から追加されたシンプルキャッシュ def fib(n: int) -> int: if n < 2: return n return fib(n - 1) + fib(n - 2) |
functools.lru_cache(maxsize=None)と同等の振る舞いですが、引数が不要でコードがすっきりします。- 型ヒントはそのまま (
int -> int) で問題なく機能し、テスト時にもキャッシュ結果を簡単に検証できます。
2‑3. デコレータ実装時の注意点(Python 3.12 向け)
| 項目 | 推奨策 |
|---|---|
functools.wraps の使用 |
常に @functools.wraps(original) を付与し、デバッグ情報と型情報を保持。 |
| 引数の受け渡し | *args, **kwargs だけでなく、ParamSpec を活用すると型安全性が向上。 |
| ドキュメント文字列 | デコレータ自身に docstring を付け、Sphinx 等の自動生成ツールでも正しく表示させる。 |
| テスト容易性 | デコレータを関数として分離し、unittest.mock でラップされた関数を差し替えてテストできるように設計する。 |
3. まとめ ― 今すぐ試したいこと
functools.cacheを自プロジェクトの再帰的・純粋関数へ導入し、ベンチマークで速度向上を確認。- デコレータ実装に
ParamSpecとTypeVarを取り入れ、IDE の補完が正しく働くかチェック。 - 既存のデコレータコードが 「括弧省略」 を前提としていないか再度レビューし、必要なら修正(
@decorator(arg)の形に統一)。
Python 3.12 はデコレータ構文そのものに大きな変化はありませんが、型ヒントのサポート強化と新しい標準キャッシュデコレータ が実務での可読性・保守性向上に直結します。正確な情報を踏まえて、コードベースにすぐ適用できる改善点から取り組んでみてください。