1. TOP
  2. プログラム
  3. ソフト
  4. python
  5. デコレーター

デコレーター

2019-04-30_090848_GX1

デコレータ

ソースコードを書き換えずに既存の関数に変更を加えたいことがある。 
よく知られているのは、引数として何が渡されたかを見るためのデバッグ
文の追加です。
デコレータは、入力として関数をひとつ取り、別の関数を返す関数
である。Pythonのトリックの山から、次のものを使う。
◎*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



document_it()にどんなfuncを渡しても、document_it()が追加した
文を含む新しい関数が返される。デコレータは、funcのコードを一切
実行しなくてもよいのだが、document_it()は途中でfuncを呼び出し
追加コードの結果とともにfuncの結果も得られるようにしている。

では、これをどのように使えばよいのだろうか。次のように手作業で
デコレータを使う



>>>def add_ints(a, b):
return a + b

>>>cooler_add_ints = document_it(add_ints)
>>>cooler_add_ints(3, 5)


Running function add_ints
Positional arguments (3, 5)
Keyword arguments {}
Result 8



上のように手作業でデコレータの戻り値を代入しなくても、
デコレートしたい関数の直前に@decorator_nameを追加すれば変更
後動作がえられます。


>>>@document_it
def add_ints(a, b):
return a + b


>>>add_ints(3,5)



Running function add_ints
Positional arguments (3, 5)
Keyword arguments {}
Result 8



関数に対するデコレータは複数もてる、結果を自乗するsquare_it()
という別のデコレーターを書いてみよう。
>>>def square_it(func):
def new_function(*arg, **kwargs):
result = func(*args, **kwargs)
return result * result
return new_function


関数に最も近いデコレーターが(defの上)が先に実行され、次にその上
のデコレーターが実行される、どの順番でも最終的な結果は同じだが、
中間の手順が変わる


>>>@document_it
@square_it
def add_ints(a, b):
return a + b

>>>add_ints(3,5)


Running function new_function
Positional arguments (3, 5)
Keyword arguments {}
Result 64