@decorator デコレータ

今回は「たまに見かけるあのコード」としてデコレータを紹介します。

デコレータはシンタックスシュガー (糖衣構文)です。シンタックスシュガーとはプログラミング言語において、ある書き方に対して別の書き方ができるようにしたものです。

通常の各関数を定義して実行する例

def first_func():
    print('1が実行されました')

def second_func():
    print('2が実行されました')

first_func()
second_func()

# 実行結果 ---
# 1が実行されました
# 2が実行されました

上記のコードでも良いが、できれば一つの関数を実行するだけで2つの関数を実行できれば便利そうです。そこで関数の引数に関数を指定していますが結果はうまくいきません。

def first_func(func):  # second_func()が引数に入ってくる
    print('1が実行されました')
    return func

def second_func():
    print('2が実行されました')

first_func(second_func)

# 実行結果 ---
# 1が実行されました
# <function __main__.second_func>

関数の実行文を書けばうまくいきます。

def first_func(func):
    print('1が実行されました')
    return func()  # 関数の実行

def second_func():
    print('2が実行されました')

first_func(second_func)

# 実行結果 ---
# 1が実行されました
# 2が実行されました

デコレータを使う場合

デコレートの機能(@)を使うとシンプルに書けます。また、デコレータの場合は実行する関数は通常通り実行するだけ大丈夫です。

def first_func(func):
    print('1が実行されました')
    return func

@first_func
def second_func():
    print('2が実行されました')

second_func()  # 直接使いたいsecond_funcを実行するだけでOK

# 実行結果 ---
# 1が実行されました
# 2が実行されました

second_func()を実行すると、自動的にfirst_funcが先に実行され、その後second_funcが実行されます。このようにデコレータは事前に、自動的に別の関数を実行したい場合に便利です。

引数を使う例

def first_func(func):
    print('1が実行されました')
    return func

# first_funcをデコレータとして使用(関数の上に追記する)
@first_func  
def second_func(name):
    print('2が実行されました')
    print(f'こんにちは{name}さん!')

second_func('Pythonマスター')

# 実行結果 ---
# 1が実行されました
# 2が実行されました
# こんにちはPythonマスターさん!

デコレータの中で引数を使う例

def first_func(func):
    print('1が実行されました')
    def wrap(*args):
        print(f'引数: {args}')  # second_funcに渡される引数をここで確認可能
        return func(args[0])
    return wrap

@first_func
def second_func(name):
    print('2が実行されました')
    print(f'こんにちは{name}さん!')

second_func('Pythonマスター')

# 実行結果 ---
# 1が実行されました
# 引数: ('Pythonマスター',)
# 2が実行されました
# こんにちはPythonマスターさん!

入門コースにおいて、デコレータを作ることはしませんが、本やネットで見かけた場合は、上記のような役割があることを思い出しましょう!