4.9 デコレータ
デコレータは、入力として関数をひとつ取り、別の関数を返す関数です。 これを使えば、既存の関数のソースコードを直接書き換えずに、新しい機能(デバッグ文の追加など)を付け加えることができます。
デコレータの仕組み
Section titled “デコレータの仕組み”デコレータを作成するには、これまでに学んだ「関数内関数」や「引数としての関数」、「*args / **kwargs」のテクニックを組み合わせます。
例として、実行される関数名と引数を表示する document_it デコレータを見てみましょう。
def document_it(func): # 元の関数をラップする新しい関数を定義 def new_function(*args, **kwargs): print('Running function:', func.__name__) print('Positional arguments:', args) print('Keyword arguments:', kwargs)
# 本来の関数を実行 result = func(*args, **kwargs)
print('Result:', result) return result
# 機能を拡張した新しい関数を返す return new_functionデコレータの使い方
Section titled “デコレータの使い方”1. 手作業で適用する
Section titled “1. 手作業で適用する”デコレータの戻り値(新しく作られた関数)を、変数に代入して呼び出します。
def add_ints(a, b): return a + b
# デコレータを適用して新しい関数を作るcooler_add_ints = document_it(add_ints)
# 新しい関数を実行cooler_add_ints(3, 5)2. @ 記法を使う(推奨)
Section titled “2. @ 記法を使う(推奨)”デコレートしたい関数の定義の直前に @デコレータ名 を追加します。これがもっとも一般的で Python らしい書き方です。
@document_itdef add_ints(a, b): return a + b
add_ints(3, 5) # 自動的に拡張された機能が実行される複数のデコレータを重ねる
Section titled “複数のデコレータを重ねる”ひとつの関数に対して、デコレータを複数重ねて使うこともできます。 この場合、関数に近い方(下にある方)のデコレータから順番に実行されます。
def square_it(func): def new_function(*args, **kwargs): result = func(*args, **kwargs) return result * result # 結果を自乗する return new_function
@document_it@square_itdef add_ints(a, b): return a + b
print(add_ints(3, 5))# 1. square_itが実行される (3+5=8, 8*8=64)# 2. document_itがその結果(64)をレポートする