ペンドリブン

1985年生まれ 仕事・家庭・etc. 雑記

*

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

 - プログラム