lispとrubyとpythonと その7 デコレータ構文(pythonだけ)
python2.4から入ったデコレータ構文。
単純なシンタックスシュガーで動作も理解しやすいけど、色々使いどころはありそう。
面白い。
#デコレータ構文 #ここの説明が一番分かりやすかった #http://morchin.sakura.ne.jp/effective_python/decorator.html #C#でいうとアトリビュート、javaでいうアノテーションのPythonでの方法。 #実装内容で見れば全然違うけど、シンタックス上は似てるし、AOPっぽい。 #関数のトレースを出力するデコレータfunc_traceがこんな感じ import datetime import functools def func_trace(f): @functools.wraps(f) #fの属性をwrapperにコピーするためのおまじない。wrapper関数をデコレートしてる。 def wrapper(*args, **kw): print("start:" + datetime.datetime.now().strftime("%Y/%m/%d %H:%M:%S") + ":" + f.__name__) rtn = f(*args,**kw) print("end:" + datetime.datetime.now().strftime("%Y/%m/%d %H:%M:%S") + ":" + f.__name__) return rtn return wrapper @func_trace def foo (): print("hello") #引数をとるデコレータ #ファイル名をとって、そのファイルに呼び出し履歴をロギングする def func_log(filnm): def deco(f): @functools.wraps(f) #fの属性をwrapperにコピーするためのおまじない。wrapper関数をデコレートしてる。 def wrapper(*args, **kw): with open(filnm,"w") as fs: fs.write("start:" + datetime.datetime.now().strftime("%Y/%m/%d %H:%M:%S") + ":" + f.__name__ + "\n") rtn = f(*args,**kw) fs.write("end:" + datetime.datetime.now().strftime("%Y/%m/%d %H:%M:%S") + ":" + f.__name__ + "\n") return rtn return wrapper return deco @func_log(".//test.log") def woo (): print ("hello") #Pythonのデコーレータ構文はタダのシンタックスシュガー #まず引数をとるデコレータは忘れておく #@xxx #def foo (): #これは #foo = xxx(foo) #と同じ意味。 #xxxは関数を引数にとる関数 #上記の例だとfooがxxxの引数に渡ってくる。 # なのでxxxでfooの前後に処理をしつつfooを呼び出す関数を返すのが一般的 # 引数をとるデコレータ # @xxx(1,2,3) # def foo(): # は # foo = xxx(1,2,3)(foo) # と同じ意味 # つまり # f = xxx(1,2,3) #fは関数をとって関数を返す関数 # foo = f(foo) # こういうこと # デコレータは複数指定できる # @aaa # @bbb # @ccc # def foo(): # だったら # f = aaa(bbb(ccc(f))) # と同じ意味になる # 適用順序に注意