猫型エンジニアのブログ

プログラム/ネットワーク系の技術関連をまとめたページです 

デコレータ

 Pythonのデコレータについてまとめました。デコレータは他の関数を引数にする関数である「高階関数」を利用しています。

デコレータの形式

@decorator
def func():
    pass

 上のようにデコレート対象の関数の頭にデコレータ用の関数を@をつけて使用します。こうすることで、以下の例のように関数funcを関数decoratorの引数として呼び出し、関数decoratorの返り値として再定義します。これにより関数funcの動作をデコレータに応じて柔軟に変更することができます。

# デコレータは以下のシンタックスシュガー。
# 名前は同じだが左辺と右辺のfuncは動作が異なる。
func = decorator(func)

デコレータの実行例

Step1 引数なしのデコレータ

def decorator(func):
    print "decorator is called."
    return func

@decorator
def f():
    print "f is called."

 関数fの実行結果は以下のようになります。確かにデコレータに応じて、関数fの動作が変更されています。

# python test.py
decorator is called.
f is called.

Step2 引数ありのデコレータ

 関数を入れ子にすることで、デコレータに引数を渡せます。デコレータの引数を受け取るwrapper関数を定義し、その内部で引数を使用するdecoratorを定義します。

def wrapper(arg):
    def decorator(func):
        print arg
        return func
    return decorator

@wrapper("decorator is called by args.")
def f(str):
    print str

 関数fを"function is called by args."を引数として実行すると、以下のようになります。

python test.py
decorator is called by args.
function is called by args.

他の書き方

 デコレータの他の書き方としては以下のような方法もあります。内部でデコレート対象の関数を実行するwrapper関数を定義しています。ただしこれだと、関数が不必要にネストしてしまいます。

def decorator(function):
    def wrapper():
        print "wrapper is called."
        return function()
    return wrapper

@decorator
def func():
    print "function is called."