Skip to content

4.9 デコレータ

デコレータは、入力として関数をひとつ取り、別の関数を返す関数です。 これを使えば、既存の関数のソースコードを直接書き換えずに、新しい機能(デバッグ文の追加など)を付け加えることができます。

デコレータを作成するには、これまでに学んだ「関数内関数」や「引数としての関数」、「*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

デコレータの戻り値(新しく作られた関数)を、変数に代入して呼び出します。

def add_ints(a, b):
return a + b
# デコレータを適用して新しい関数を作る
cooler_add_ints = document_it(add_ints)
# 新しい関数を実行
cooler_add_ints(3, 5)

デコレートしたい関数の定義の直前に @デコレータ名 を追加します。これがもっとも一般的で Python らしい書き方です。

@document_it
def add_ints(a, b):
return a + b
add_ints(3, 5) # 自動的に拡張された機能が実行される

ひとつの関数に対して、デコレータを複数重ねて使うこともできます。 この場合、関数に近い方(下にある方)のデコレータから順番に実行されます。

def square_it(func):
def new_function(*args, **kwargs):
result = func(*args, **kwargs)
return result * result # 結果を自乗する
return new_function
@document_it
@square_it
def 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)をレポートする