Pythonには「デコレータ」(decorator) という機能が標準で提供されています。
デコレータはPython以外のプログラミング言語ではあまり見ないので、少々とっつきにくい印象を受けます。
このエントリでは、Pythonのデコレータについて説明し、その使い方を紹介します。
デコレータとは「関数を受け取って関数を返す関数」です。
関数fは関数gを受け取って関数g'を返している
プログラミングにおいては「関数を受け取る関数」や「関数を返す関数」のことを高階関数と言います。
コードでデコレータの例を見てみましょう。
Pythonでデコレータを定義するにはfunctoolsからwraps関数をインポートします。
from functools import wraps
def to_john(f):
@wraps(f)
def wrapper():
return f() + ' John!'
return wrapper
@to_john
def say_hello():
return 'Hello!' 上記の例で、to_john()関数がデコレータです。
to_john()関数は引数fを受け取り、内部で定義したwrapper()関数を返しています。
wrapper()関数は、引数fをf()のようにして関数呼び出しし、f()の戻り値と' John!'と結合した結果を返しています。
このことから、デコレータの条件のうち「関数を返す関数」であるというのはわかりました。
しかしデコレータは「関数を受け取る関数」でもあります。
「受け取る関数」はどこで定義しているのでしょうか?
デコレータを使って関数をデコレート(decorate/修飾)するには、修飾したい関数の上に@decoratorのように表記します。
@to_john
def say_hello():
return 'Hello!' 例では、デコレータ@to_johnがsay_hello()関数をデコレートしています。
つまり、デコレータto_john(f)の引数fの正体は、デコレートされる関数(この場合はsay_hello())であるというわけです。
>>> say_hello()
Hello! John! ところで@wraps(f)は何をしているのでしょうか?
wrapsデコレータは、内部的にデコレータ関数(wrapper関数)がデコレートされる側の関数(wrapped関数)に見えるようにしています。
これは、デコレータ関数でエラーが発生した場合などに役立ちます。
詳しくは下記をご覧ください。
以上です。このエントリでは、Pythonのデコレータについて説明し、その使い方を紹介しました。
コメントを送る
コメントはブログオーナーのみ閲覧できます