Python のデコレータは、関数やメソッドの振る舞いを変更するために使用される特殊な機能です。
デコレータ
は、関数を引数として受け取り、新しい関数を返す関数です。
デコレータ
は、@
記号を使用して簡単に適用することができます。
デコレータの例
例えば、次のようなデコレータがあります。
def my_decorator(func):
def wrapper():
print("Something is happening before the function is called.")
func()
print("Something is happening after the function is called.")
return wrapper
このデコレータは、my_decorator
という名前の関数で定義されています。
この関数は、func
という名前の引数を受け取り、新しい関数wrapper
を返します。wrapper
関数は、func
が呼び出される前後に何かを行います。
デコレータ
の適用
このデコレータ
を使用するには、次のようにします。
@my_decorator
def say_hello():
print("Hello!")
say_hello()
このコードは、次のような出力を生成します。
Something is happening before the function is called.
Hello!
Something is happening after the function is called.
@記号を使用せずにデコレータ
を適用することもできます。次のようにします。
def say_hello():
print("Hello!")
say_hello = my_decorator(say_hello)
say_hello()
このコードも、同じ出力を生成します。
@記号の利点
@記号を使用することで、デコレータ
の適用が簡単になります。
say_hello = my_decorator(say_hello)
@を適用しない場合、この一行が必要となり、作らなくてもよい変数を実装することになります
クロージャ
クロージャ
とは、関数内部で定義された関数です。
クロージャ
は、外部関数のローカル変数にアクセスすることができます。
上記の例では、wrapper
関数がクロージャです。
wrapper
関数は、外部関数my_decorator
の引数func
にアクセスしています。
デコレータの実装は再利用性があるということがピックアップされて語られることが多いのですが、クロージャという仕組みを理解しなければ外部関数の引数であるfunc
を呼び出す理由を思いつくことができません。
今回の実装で言うと、my_decorator
は wrapper
という関数をreturnし、say_hello()
を実行する時点で、中身は wrapper関数
に差し代わっています。
デコレータの動作を一言で表すなら単に 対象オブジェクトを差し替える 技術です。
そしてwrapper関数を実行するわけですが、そのなかにfunc
関数があり、そのfuncはどこから参照しているのかというと my_decorator(func)
の func
から参照しているのです。
なぜそれが可能かといえばクロージャーの仕組みを用いて func
が say_hello
関数のアドレスを参照するようにし、プログラムが実行可能となっています。
下記の画像はクロージャを使って外部関数に対する値を参照したイメージ図となります
デコレータは、コードの再利用性を高めるために使用されます。
例えば、複数の関数で共通の前処理や後処理が必要な場合、デコレータを使用することで、その処理を一箇所にまとめることができます。
デコレータは非常に強力な機能であり、コードの再利用性や可読性を高めることができます。