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関数が返ってきているのがわかります🍰
わかると案外あっさりですね。
それでは、楽しいデコレータライフを✨