見出し画像

Python日記vol.11🐍デコレータ

こんにちは。aliceです。
あたたかいお茶とケーキが合う季節になりましたね☃
濃いめの紅茶とチョコレートケーキを食べたいです🎂

デコレータとは

今日はデコレータのはなしです。
デコレータは関数で機能を追加したいときに使います。デコレータを使うと既存の関数を変更せずに、新しい機能を追加できます。


こんな関数を作りました。

def eat_cake():
    print('ケーキおいしい!幸せ!(◕‿◕✿)')

おいしいケーキは幸せですね。わかります。


でもせっかくだから「ケーキおいしい」だけではなくて「いただきます」と「ごちそうさま」を言いたいですよね。

ということで書き直しました。

def eat_cake():
    print('いただきます(●ˇ∀ˇ●)')
    print('ケーキおいしい!幸せ!(◕‿◕✿)')
    print('ごちそうさまでした(✿◡‿◡)')

お行儀のよい関数ができました。


ケーキだけだと力がでないので、お肉も食べたいと思います。

def eat_stake():
    print('ステーキおいしい!おなかいっぱい(❁´◡`❁)')

おいしいステーキは幸せですね。わかります。

でもせっかくだから「ステーキおいしい」だけではなくて「いただきます」と…以下略。

ということで書き直しました。

def eat_stake():
    print('いただきます(●ˇ∀ˇ●)')
    print('ステーキおいしい!おなかいっぱい(❁´◡`❁)')
    print('ごちそうさまでした(✿◡‿◡)')

お行儀のよい関数ができました(2回目)


でも機能を追加するたびに書き直したり、新しい関数を作るのは大変ですよね。


そんなときに使うのがデコレータ。

デコレータを使うと、もとの関数を変えずに機能を追加することができます。

def say_greeting(func):
    def wrapper():
        print('いただきます(●ˇ∀ˇ●)')
        func()
        print('ごちそうさまでした(✿◡‿◡)')

    return wrapper


@say_greeting
def eat_cake():
    print('ケーキおいしい!幸せ!(◕‿◕✿)')


eat_cake()


eat_cake関数を実行するとこのように出力されます。

いただきます(●ˇ∀ˇ●)
ケーキおいしい!幸せ!(◕‿◕✿)
ごちそうさまでした(✿◡‿◡)

eat_cake関数の中身を変えずに「いただきます」と「ごちそうさま」を言うことができました。


前振りが長くなりましたが、今日はデコレータを作っていきたいと思います。


引数として関数を受け取る

まず、関数の引数として関数を受け取るところから始めましょう。
うーん、何を言っているのでしょうか💦

こんな関数を作りました。
say_greeting関数は引数としてeat_cake関数を受け取っています。

def say_greeting(func):
    print('いただきます(●ˇ∀ˇ●)')
    func()
    print('ごちそうさまでした(✿◡‿◡)')


def eat_cake():
    print('ケーキおいしい!幸せ!(◕‿◕✿)')


say_greeting(eat_cake)


実行するとこのように出力されます。

いただきます(●ˇ∀ˇ●)
ケーキおいしい!幸せ!(◕‿◕✿)
ごちそうさまでした(✿◡‿◡)


せっかくなのでステップイン実行してみていきましょう。

say_greeting関数を実行します。
引数としてeat_cake関数を渡しています。


say_greeting関数は引数としてeat_cake関数を受け取っています。
まず「print('いただきます(●ˇ∀ˇ●)')」が実行されます。

「いただきます(●ˇ∀ˇ●)」と出力されました。


次は「func()」が実行されます。
funcはeat_cake関数でしたね。

func()でeat_cake関数を実行します。


eat_cake関数が呼び出されました。
「print('ケーキおいしい!幸せ!(◕‿◕✿)')」が実行されます。


「ケーキおいしい!幸せ!(◕‿◕✿)」と出力されました。


最後に「print('ごちそうさまでした(✿◡‿◡)')」が実行されます。


「ごちそうさまでした(✿◡‿◡)」と出力されました。


無事に関数が実行されました🎂

このように関数は引数として関数を受け取ることができます。



関数を戻り値として返す

次は関数を戻り値として返してみましょう。
うーん、何を言っているのでしょうか💦

このような関数を作りました。
say_greeting関数ではwrpper関数が定義されていて、wrpper関数を戻り値として返します。

def say_greeting(func):
    def wrapper():
        print('いただきます(●ˇ∀ˇ●)')
        func()
        print('ごちそうさまでした(✿◡‿◡)')
    return wrapper


def eat_cake():
    print('ケーキおいしい!幸せ!(◕‿◕✿)')


new_func = say_greeting(eat_cake)
new_func()


「return wrapper」なのでwrapper関数が戻り値ですね。


こちらもせっかくなのでステップイン実行してみていきましょう。

まずsay_greeting関数を実行します。
引数としてeat_cake関数を渡しています。先ほどと同じです。


say_greeting関数は引数としてeat_cake関数を受け取っています。
これも先ほどと同じです。


新しく作ったwrapper関数を実行しないで戻り値として返します。
定義しているだけなので実行しないで返します。


new_funcはwrapper関数を受け取ります。


new_funcにはsay_greeting関数の戻り値のwrapper関数が入りました。


new_func関数を実行します。
new_func関数は新しく作ったwrapper関数でしたね。

ということでwrapper関数が実行されます。
ここからは先ほどと同じです。


同じように出力されました。

ちゃんとデコれました🎂
わーい!



再びデコレータとは

先ほどはこのようにデコレータを書きました。

new_func = say_greeting(eat_cake)
new_func()


でもこのように書くのは面倒ですよね。

デコレータは「@」にデコレータ関数の名前を装飾したい関数の上に書いて使うことができます。

def say_greeting(func):
    def wrapper():
        print('いただきます(●ˇ∀ˇ●)')
        func()
        print('ごちそうさまでした(✿◡‿◡)')

    return wrapper


@say_greeting
def eat_cake():
    print('ケーキおいしい!幸せ!(◕‿◕✿)')


eat_cake()


次の2つは同じ意味です。

@say_greeting
def eat_cake():
    print('ケーキおいしい!幸せ!(◕‿◕✿)')


def eat_cake():
    print('ケーキおいしい!幸せ!(◕‿◕✿)')


eat_cake = say_greeting(eat_cake)
eat_cake()


わかるとあっさりですよね。


new_funcにeat_cakeを代入してnew_funcを実行すると、wrapper関数が返ってきているのがわかります🍰


わかると案外あっさりですね。
それでは、楽しいデコレータライフを✨

この記事が気に入ったらサポートをしてみませんか?