pythonのデコレータ
2016/01/15
pythonのデコレータについてのメモ。
関数とかの上に良く見かける「@xxx」みたいなやつ。
こいつができた経緯は「エキスパートPythonプログラミング」のP76によると下記のような動機からのようです。
クラスメソッドや静的なメソッドを定義する際に、メソッド定義の前の行にすっきりと書けるようにしたい
デコレータを使用しない場合
class SayHellow():
def say_good_morning(self):
print "Good Morning!"
say_good_morning = classmethod(say_good_morning)
>>SayHellow.say_good_morning()
Good Morning!
Python2.3まではsay_good_morningメソッドをSayHellowクラスのクラスメソッドにするには、上記のようにする必要があったようですが、Python2.4で追加されたデコレータを利用すれば下記のようになり、読みやすくなります。
デコレータを使用した場合
class SayHellow():
@classmethod
def say_good_morning(self):
print "Good Morning"
>>SayHellow.say_good_morning()
Good Morning!
自分でデコレータを作る場合
「エキスパートPythonプログラミング」のP77によると、
デコレータ関数の中で、元の関数を呼び出すサブ関数を定義し、それを返すという方法がもっともシンプルで読みやすいでしょう。
とのこと。
@add_everyone
def good_evening():
return "Good Evening!"
Good Evening! Everyone.
上記の@add_everyoneデコレータは、good_evening関数が返す「Good Evening!」の後ろに「Everyone.」をつけてprintするデコレータとすると、下記のように@add_everyoneデコレータは実装される。
def add_everyone(func):
def _deco():
print func() + "Everyone."
return _deco
funcにはデコレータをつけた関数が入るので、ここではgood_eveningが入ることになる
つまり、@add_everyoneをつけたgood_evening関数は、add_everyone関数の引数として代入され、good_evening関数がreturnした「Good Evening!」に「Everyone.」を足してprintするので下記のようなイメージ。
def add_everyone(good_evening):
def _deco():
print good_evening() + "Everyone." # good_eveningは「Good Evening!」を返す。
return _deco
