Python

Pythonのデコレーターの基本

プログラムみてたらメールアドレスみたいな記号がでてきて理解できません。。
アットマーク”@”のことかな? それはデコレーターだね。

はじめのうちはデータ処理を自分で行っている段階ではあまり使用しませんが、他人が書いたプログラミングで
「デコレーター」というものを見かけることがあります。

デコレーターは

@デコレーター関数
def 修飾される関数():
———

というような書式です。

@は半角のアットマークです。
オシャレな感じですが、使い慣れない記号のため最初は理解しにくいです。

このページの内容
  • デコレーターは関数を修飾する関数
  • デコレーターには関数を入れて関数が出てくる
  • 修飾する関数の定義(def)の上に@で書き加える

関数を修飾する関数

単純な関数で説明します。
名前を言う「say_name」という関数を
前後に挨拶を付け加える「wrap」関数で修飾します。


"""名前を言う関数"""
def say_name():
    print("I am Mike")

say_name()

I am Mike

名前が表示されます。

名前の関数に加え
「引数で入れた関数の前後に挨拶を入れた関数を返す」
関数「wrap」を定義します。

ポイントは
「関数を入れて関数が出てくる」
というところです。


def say_name():
    print("I am Mike")

"""デコレート関数"""
def wrap(func):   #引数は関数
    """関数内で関数を定義し、前後を修飾"""
    def add_hello():
        print('Hello!')
        func()    #引数の関数を実行する
        print('Good Bye!')

    return add_hello    #返り値は関数

say_name = wrap(say_name)  
#say_nameをwrap関数で修飾した関数に置き換える

say_name()
#置き換えたsay_nameを実行

Hello!
I am Mike
Good Bye!

前後にwrapで加えた部分の文章が出力されます。

@デコレーターの形式で書き換える

修飾される関数「say_name」の定義と
修飾した関数におきかえる行である

def say_name():
    print("I am Mike")
say_name = wrap(say_name) 

の部分を

@wrap
def say_name():
    print("I am Mike")

で置き換えることができます。

全体を書き換えると


"""デコレート関数"""
def wrap(func):
    def hello():
        print('Hello!')
        func()
        print('Good Bye!')
    return hello

@wrap  #直下の関数をwrap関数によってデコレートしている
def say_name():
    print("I am Mike")

say_name()

Hello!
I am Mike
Good Bye!

となります

同じ関数でいくつもデコレートされるときなどは

@デコレート関数
def function():

の形式の方がわかりやすいですね。

ちょっと強引ですが、こんな感じでしょうか。↓

引数をとる場合は*argsや**kwargsを使ったりしますが、多くの教材でデコレーターとこれらの変数を一気に学習しようとするので混乱します。

ここでは、
「デコレーターは関数を修飾する関数」
という役割を覚えておけば十分です。