関数の上についてる@マークもといデコレータについて
細かい事は置いといて、デコレータってどんなことしてるの?という記事です。
実例
内容はひとつの関数で書けというものですが、とりあえず実例を出します。
コード
#デコレータを定義
def greet(func):
def inner(*args,**kwargs):
print("こんにちは。")#1
result = func(*args,**kwargs)#2
print("よろしくお願いします。")#3
return result#4
return inner
#使い方
@greet
def myName(name):
print(f"私は{name}です。")
return "挨拶 終"
print(myName("ねこでべろん"))
結果
こんにちは。
私はねこでべろんです。
よろしくお願いします。
挨拶 終
解説
myName()の上に@greetを付ける事でmyName()をgreet()でデコレートしました。
#1 デコレータが「こんにちは。」と出力
#2 myName()を実行。名前を出力し返り値をresultに格納
#3 デコレータが「よろしくお願いします。」と出力
#4 返り値を返す(printで出力される)
このような流れで実行されます。
どんなイメージなのか
少しコードを変えます
コード
#デコレータを定義
def greet(func):
def inner(*args,**kwargs):
print("こんにちは。")
result = func(*args,**kwargs)#関数本体
print("よろしくお願いします")
return result
return inner
#@greet
def myName(name):
print(f"私は{name}です。")
return "挨拶 終"
#print(myName("ねこでべろん"))
print(greet(myName)("ねこでべろん"))
結果
こんにちは。
私はねこでべろんです。
よろしくお願いします。
挨拶 終
解説
さっきとほとんど変わりません。@greetをやめて、
myName("ねこでべろん")をgreet(myName)("ねこでべろん")に変えただけです。そしてこれこそがデコレータの本質です。
greet(myName)によってfuncにmyNameが代入されたinnerという関数が返ってきます。よってgreet(myName)("ねこでべろん")はinner("ねこでべろん")を実行している事になります。
その結果inner内の処理が順に実行されていきfuncではmyNameが代入されているのでその処理が行われます。
つまり、@greetはこの一連の流れを簡単に記述するために使われているということです。
ところで*args、**kwargsって何者
メインではないので少しだけ紹介程度に。
*args、**kwargsは可変長引数と呼ばれるものです。
*argsが普通の引数、**kwargsが引数名を指定した引数をそれぞれ格納します。
args、kwargsの文字であることに意味はありません。重要なのは*と**です。argsはarguments、kwargsはkeyword argumentsの略語で慣例的に使われています。
ちょっとした実例
def task(day,task,limit):
print(f"{day}は{task}を{limit}までにする")
task("土曜日","買い物",limit="15時")
"土曜日"と"買い物"は*args、limit="15時"は**kwargsに格納されます。
一般化したデコレータ
一応貼っときます
def decorater(func):
def inner(*args,**kwargs):
toDo()
result = func(*args,**kwargs)
toDo()
return result
return inner
最後に
私的にわかりやすい解説を作りました。
ミスなどあればお知らせください。