【例 1.4】
IDLE → New File → Save as .. → Run
def deco1(fx):
def inner(*args, **dics):
print('before:')
return fx(*args, **dics)
return inner
@deco1
def fun1():
print('f')
• このようにすると,主人公の関数fun1()に引数がない場合,可変長の場合,辞書型引数の場合のいずれの場合でも,
*args, **dicsが受け止めることができる.また,関数fun1()は,return
fx(
*args, **dics)によって実行される.
• return
innerは,
fun1 = deco1(
fun1)における左辺への代入に対応しており,このreturn
innerがないと,fun1() TypeError: 'NoneType' object is not callableというエラーメッセージが表示される.
• 例1.4によって,目標とするデコレータとしては正常に作動するが,return
fx(
*args, **dics)によって,主人公の関数fun1()を実行するところが難点となる.なぜなら,そのようにすると,必ず最後にfx()が実行されることになり,前処理'before'には対応できても,後処理を書く余地がなくなる.そこで,次の形に書きなおすと,後処理もできるようになる.'after'の箇所に後処理を書く.
(デコレータ関数の完成系1)
【例 1.5】
IDLE → New File → Save as .. → Run
def deco1(fx):
def wrapper(*args, **dics):
print('before:')
tmp = fx(*args, **dics)
print('after')
return tmp
return wrapper
@deco1
def fun1():
print('f')
• 多くの教科書で,デコレータ関数の入れ子の関数は,修飾される方の主人公となる関数fx()を包み込む関数という意味で,ラッパーという用語が使われているので,ここでもその用語にした…サランラップ,クレラップのラップ(wrap)は「包むもの」という名詞にもなり,「包む」という動詞にもなる.
(UNIXのシステムでは,TCP wrapperが使われていて,何らかのコマンドを受け付けるための前処理やアクセスログの記録などを行うらしい.)
次のようにデコレータを使うと,アクセスした,日時,関数名,引数がc:/???/log1.txtというファイルに記録される.
【例 1.6】
IDLE → New File → Save as .. → Run
import datetime as dt
dt1 = dt.datetime
def deco1(fx):
def wrapper(*args, **dics):
tmp = fx(*args, **dics)
with open('c:/???/log1.txt','a') as file1:
file1.write(str(dt1.now())+',')
file1.write(fx.__name__+',')
file1.write(str(args)+'\n')
return tmp
return wrapper
@deco1
def fun1(str1):
print(str1)
@deco1
def fun2(str2):
print(str2)
fun1('abc')
fun2('xy')