【python】デコレータとは?4ステップで分かりやすく解説

スポンサーリンク
【python】デコレータとは?4ステップに分けてわかりやすく解説 基礎
この記事を読んで分かること
  • デコレータとは何か
  • デコレータの挙動

 

デコレータとは

Pythonのデコレータ(decorator)とは、

関数の前後に特定の処理を追加して拡張するための機能

です。

 

デコレータは、通常、@decoratorという構文を使用して関数やメソッドの定義の直前に適用されます。

以下に、基本的なデコレータの例を示します。

def my_decorator(func):
    def wrapper(*args, **kwargs):
        print("start")
        func(*args, **kwargs)
        print("end")
    return wrapper

@my_decorator
def say_hello():
    print("Hello!")

say_hello()
start
Hello!
end

 

この例では、my_decoratorというデコレータが定義されています。

そして、say_hello関数の前に@my_decoratorが付いていて、これによりsay_hello関数がmy_decoratorで修飾されることになります。

say_hello関数を実行結果を見るとデコレータ内の処理が追加されていることがわかると思います。

 

デコレータの挙動

先ほど例示したこちらのコードで挙動を解説していきます。

def my_decorator(func):
    def wrapper(*args, **kwargs):
        print("start")
        func(*args, **kwargs)
        print("end")
    return wrapper

@my_decorator
def say_hello():
    print("Hello!")

say_hello()

デコレータ(my_decorator関数)が適用されたsay_hello関数を呼び出すと、実際にはラップされたwrapper関数が呼び出されます。

挙動としては、

my_decorator(say_hello)()

が実行されたことと同義になります。

my_decoratorの引数にsay_hello関数を指定し、my_decorator関数内に定義されたwrapper関数がsay_hello関数を実行する形となっています。

wrapper関数内で、元の関数(func)を呼び出す前後に追加の処理print(“start”)やprint(“end”)が記載されています。

このprint(“start”)やprint(“end”)といった前後に追加する処理をデコレータによって使い回すことが容易になっています。

 

デコレータをより理解するための解説

デコレータをより理解するためにステップに分けて解説します。

ステップ1:関数

まずは、一般的な関数の定義です。

defキーワードにより関数名と処理を定義しています。

def func1():
    print("func1の実行")

func1()
func1の実行

 

func1関数を実行すると、定義したprint関数が呼び出されていることが分かります。

 

ステップ2:関数の引数

今度は、引数を与える関数の定義です。

関数を引数としてもらい、その関数を実行する関数func2を定義しています。

def func2(f):
    f()

func2(func1)
func1の実行

 

func2が引数としてfunc1関数を受け取り、func1関数を実行していることが分かります。

ちなみに、引数として与えられているfunc1は関数オブジェクトのアドレスで、f()とすることで関数オブジェクトを実行しています。

 

ステップ3:デコレータ

いよいよデコレータを作成します。

関数fを引数として受け取り、内部のwrapper関数内で関数fを実行する作りとなっています。

def func3(f):
    def wrapper():
        print("start")
        f()
        print("end")
    return wrapper

func = func3(func1)
func()
start
func1の実行
end

 

func3の引数としてfunc1関数を与えていますが、func3はwrapper関数のオブジェクトを返すだけです。

そのため、func3を実行するだけでは、func1が実行されることはありません。

戻り値であるwrapper関数オブジェクトを代入したfunc変数を実行することで、func1と前後の処理が動作します。

 

ステップ4:@シンボルの適用

@シンボルを使って関数を定義することで、デコレータを呼び出すfunc3(func4)のfunc3()の部分を省略することができます。

@func3
def func4():
    print("func4の実行")

func4()
start
func4の実行
end

 

func4を呼び出すだけで、デコレータ内の処理を実行されていることが確認できます。

 

参考文献

Pythonのデコレータを理解するための12Step - Qiita
古い記事なんですが, Pythonのデコレータの概念をつかむには良記事だったので和訳意訳してみました.…

コメント

タイトルとURLをコピーしました