はじめに
Python で全ての関数の実行前後に共通で開始と終了メッセージを表示させる効率的の方法がないかを調べていた時に見つけました。
デコレータ [decorator]
デコレータとは
関数をデコレート(ラッピング)することで、デコレートされた関数を実行する残後にコードを実行することができる機能。
実装例
import functools
def trace(f):
@functools.wraps(f)
def decrated_function(*args, **kwargs):
print(f'TRACE-S: {f} {args} {kwargs}')
result = f(*args, **kwargs)
print(f'TRACE-E: {result}')
return decrated_function
@trace
def hoge(arg1, arg2):
print('exec hoge.')
hoge('a', 'b')
# TRACE-S: <function hoge at 0x000001E0FFD27B50> ('a', 'b') {}
# exec hoge.
# TRACE-E: None
補足
- 入力関数(上記だとhoge)のメタデータアクセスしようとするとカスタムデコレータ(上記だとtrace)のメタデータが表示されるため、@functools.wraps(f)をカスタムデコレータに適用することで入力関数(上記だとhoge)のメタデータを引き継ぐようにする。
デコレータを複数適用する場合
下から順に適用される。
@decorator2
@decorator1
def xxxxx:
pass
# -> decorator2(decorator1(xxxxx))()
参考資料
- 『Pythonトリック』
https://www.amazon.co.jp/Python%E3%83%88%E3%83%AA%E3%83%83%E3%82%AF-Dan-Bader/dp/4798157678
おわりに
業務処理と共通処理を分離できるので効果的かなと。例外発生時のログ出力とかもログ機能と絡めて共通化して切り離せると尚よいですね。