今日はデコレータをやっていきます。
既存のプログラムを使用しているときに、ちょっとこの関数に機能を追加したいなあ、なんて思ったことありませんか?
デコレータ追加前
|
# 普通の関数 def add_num(x, y): return x + y result=add_num(100, 200) # result = 300 |
引数xと引数yを足した数値を返す機能を”基本機能”と呼びましょう。
これに、機能を追加(デコレート)していきましょう。
デコレーターを使わない場合
その前に、このスクリプトに対して単純に機能を追加するならば下記のようになりますよね。print()という機能をresultを算出する前後に追加しました。
|
# 普通の関数 def add_num(x, y): return x + y print('関数実行の前に、何かの処理') result=add_num(100, 200) # result = 300 print('関数実行の後に、何かの処理') print(result) """ 関数実行の前に、何かの処理 関数実行の後に、何かの処理 300 """ |
しかし、これではadd_numするたびに毎回print()→add_num→print()と3行書かなくてはなりません。
デコレータを使った場合
ここでデコレータの出番です。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
|
def deco(func): def wrapper(*args, **kwards): print('関数実行の前に、何かの処理:足し算しますよー') result = func(*args, **kwards) print('関数実行の後に、何かの処理:終わりましたよー') return result return wrapper @deco def add_num(x, y): return x + y r=add_num(100,200) print(r) """ 関数実行の前に、何かの処理:足し算しますよー 関数実行の後に、何かの処理:終わりましたよー 300 """ |
デコレータの動きを解説
まず、通常の関数定義 def add_num(x, y): の前行に @deco とつけます。
このdecoという名称が、これから作る追加機能(デコレータ)の名称になります。(任意の名前で結構です)
@decoの前行に デコレータ関数定義 def deco(func):をします。
このdef decoの引数funcには、関数add_num実行時に@decoで指定されているので、add_numが入ってきます。
デコレータ関数decoはwrapperというものをreturnするようにしますが、このwrapperを デコレータ関数内のインナー関数として定義します。def wrapper():
引数にはタプルでもディクショナリでもどちらでも入るように、def wrapper(*args, **kwargs):にしておきます。
この中に、下記3行を書き実行します。この前後print文が今回追加した(デコレートした)機能です。ここのfuncの引数にも、入ってきた引数が何であれ全て受け入れます。つまり、そのまま返すということです。
print(‘関数実行の前に、何かの処理:足し算しますよー’)
result = func(*args, **kwargs)
print(‘関数実行の後に、何かの処理:終わりましたよー’)
これで、デコレータ関数の作成はおわりました。
実行
実行するときは
r=add_num(100,200)
print(r)
とすれば、add_numの基本機能の他にデコレータの追加機能も合わせて処理が行われます。
【実行結果】
- 関数実行の前に、何かの処理:足し算しますよー #デコレータによる追加機能
- 関数実行の後に、何かの処理:終わりましたよー #デコレータによる追加機能
- 300 #基本機能