【Python】Decoratorにはどんなものがあるのか?

この記事は約5分で読めます。

デコレータ(Decorator)は、Pythonを読み始めたときにつまずきやすいポイントですが、「JavaのAOP(アスペクト指向)」「WebフレームワークのInterceptor/Filter」のイメージをお持ちであれば、まさにそれです。

開発をしていてしばしば「共通処理をビジネスロジックから切り離したい(関心の分離)」という欲求がありますが、デコレータはそのための仕組みです。

機能追加系のデコレータ

ドキュメント生成ツールやWeb開発でよく見る、3つの具体的な「あるある」パターンを紹介します。


1. 「時間計測」のデコレータ

ドキュメント生成は「重い処理」になりがちです。「PDF生成に何秒かかったか知りたい」という場合、関数の前後に時間を測るコードを書くと、コードが汚れますよね。

デコレータがない場合(コードが汚れる)

Python

デコレータがある場合(スッキリ!)

Python

解説: ソースコードを読む際、@measure_time のような記述を見つけたら、「あ、この関数は実行時間をログに残すんだな」と理解して、中身のロジックに集中すればOKです。


2. 「認証・権限チェック」のデコレータ

「管理者(Admin)しか実行できない処理」を作るときによく使われます。Javaの Filter に近いです。

Python

解説: 関数が実行されるに、デコレータが割り込んで「ログインしてる?」「管理者?」をチェックします。もし条件を満たしていなければ、delete_all_documents 本体は実行されずにエラーが返されます。


3. 「リトライ(再試行)」のデコレータ

ドキュメント生成では、外部のAPIからデータを取ってくることがあります。ネットワークが一瞬切れただけでエラーにして良いでしょうか? 数回はリトライしたいですよね。

Python

解説: これを自力で while 文と try-except で書くと、可読性が一気に下がります。デコレータのおかげで、「データ取得」という本来の目的が明確になります。


番外編:最近よく見る @dataclass

厳密には「処理を挟む」というより「クラスを改造する」デコレータですが、最近のPythonプロジェクトでは必須知識です。

Java/C#のDTO(Data Transfer Object) を作るイメージです。

Python

読み方のコツ

ソースコードを読んでいて @ が出てきたら、以下の手順で解読してください。

  1. 名前を見る: @transaction(DBトランザクション管理かな?)、@cache(結果をキャッシュするのかな?)など、名前で推測できることが多いです。

  2. 無視して本体を読む: デコレータはあくまで「付加機能」です。まずは関数本体(ビジネスロジック)が何をしているかを理解してください。

  3. 気になったら定義元へジャンプ: 「このデコレータ、具体的に何をしてるんだろう?」と思ったら、定義元(F12キーなど)に飛んでみてください。中に def wrapper(...): という関数があり、そこで func() を呼び出している構造が見えるはずです。

振る舞い変更系(設定系)の組み込みデコレータ

先ほど説明した「ログ出力」や「認証」のような「機能追加系」のデコレータとは少し毛色が違い、@staticmethod「振る舞い変更系(設定系)」の組み込みデコレータです。

@staticmethod は、Java/C# の static メソッドと同じです。

なぜわざわざ @ を付けて宣言する必要があるのか、Pythonの仕組みと合わせて解説します。


1. なぜ @staticmethod が必要なのか?

Pythonのクラス内の関数(メソッド)は、デフォルトで「インスタンス・メソッド」として扱われます。 これは、「第一引数に必ずインスタンス自身(self)を受け取る」という決まりがあるからです。

Python

しかし、クラスの中には「インスタンスのデータ(self)を使わない、単なる便利関数」を置きたいときがありますよね? そこで @staticmethod をつけると、Pythonに対して「この関数を呼ぶときは self を渡さないでください(ただの関数として扱ってください)」と指示することができます。

2. コードで比較すると分かりやすい

例えば、ドキュメント生成ツールなどであれば、「ファイルパスの操作」や「日付のフォーマット」などの便利関数でよく使われます。

Python

3. いつ使うべき?

コードレビューの際、以下のような基準で見ると良いです。

  1. 「この関数内で self を一度も使っていないな」と気づいたら、@staticmethod にすることを検討します。

  2. 目的: 「この関数は、クラスの状態(メンバ変数)を書き換えたり読み込んだりしませんよ(=副作用が少ないですよ)」ということを読み手に明示するためです。

補足:もうひとつの兄弟 @classmethod

似たものに @classmethod があります。これもよく出てきます。

  • @staticmethod: 引数に何も特別なものを受け取らない。(ただの関数)

  • @classmethod: 第一引数に クラス自身 (cls) を受け取る。

これは「ファクトリーメソッド(インスタンスを生成するメソッド)」を作るときによく使われます。

タイトルとURLをコピーしました