今回は関数デコレーターを
実装してデコレーターに
ついて説明していきます
[PR]※本サイトにはプロモーションが含まれています
関数デコレーターとは?
メイン処理(関数)をデコレート(装飾)する機能です
デコレーターを使用すると
メイン処理の関数の中身を変えずに
「@ デコレーター名」と1行追加するだけで
デコレートすることができます
具体例として
以下コードを実行し説明します
import datetime
def print_datetime(f):
# print_datetime内でwrapper関数が定義されている
def wrapper():
print(f"start: {datetime.datetime.now()}")
f()
print(f"end: {datetime.datetime.now()}")
# wrapper関数をオブジェクトとして返す
return wrapper
@print_datetime
def print_greeting():
s = input("あなたのお名前は? : ")
print(f"こんにちわ {s} さん")
print_greeting()
実行結果は
メインの処理は名前と
挨拶をする処理です
実行結果を確認すると
実行前と後の時刻が記録が
挿入されていることが確認できました
これがデコレーションです
デコレーターは関数を利用して実装されます
デコレーターのアルゴリズムを
理解するためには
pythonの関数の特性を
理解することが必要です
関数の特性について説明しながら
最終的にデコレーターを実装していきます
関数は引数に関数オブジェクトを渡すことができる
Pythonでは関数の引数に
関数オブジェクトを渡すことで
他の関数で別の関数を利用することができます
以下のコードで説明します
def call_greeting(f):
f()
# 名前を入力し挨拶される関数
def print_greeting():
s = input("あなたのお名前は? : ")
print(f"こんにちわ {s} さん")
call_greeting(print_greeting)
1.call_greeting関数の引数fに
print_greeting関数オブジェクトを渡し
call_greeting関数を呼び出す
2.f()でprint_greeting関数を実行
実行すると
といった実行結果が出てきます。
関数内関数
Pythonは関数内に関数を定義し
オブジェクトとして返すことができます
以下のコードで説明をします
import datetime
def print_datetime():
# print_datetime内でwrapper関数が定義されている
def wrapper():
print(f"start: {datetime.datetime.now()}")
print("こんにちわ")
print(f"end: {datetime.datetime.now()}")
# wrapper関数をオブジェクトとして返す
return wrapper
# wrapperオブジェクトをfuncに格納する
func = print_datetime()
func()
上記のコードは
print_datetime関数内に
wrapper関数を定義し
wrapper関数をオブジェクトとして
funcに返し
func()でwrapperを実行する
コードになります
funcはオブジェクトなので
func()を行うことでwrapperの実行結果を
出力することが可能になります
実行すると
といった結果が得られました
関数でデコレーター機能を実装する
Pythonでは関数の引数に
関数オブジェクトを渡すことで
他の関数で別の関数を利用することができる
Pythonは関数内に関数を定義し
オブジェクトとして返すことができる
この二つの性質を利用して
デコレーターを実装していきます
import datetime
def print_datetime(f):
# print_datetime内でwrapper関数が定義されている
def wrapper():
print(f"start: {datetime.datetime.now()}")
f()
print(f"end: {datetime.datetime.now()}")
# wrapper関数をオブジェクトとして返す
return wrapper
# 名前を入力し挨拶される関数
def print_greeting():
s = input("あなたのお名前は? : ")
print(f"こんにちわ {s} さん")
# wrapperオブジェクトをfuncに格納する
func = print_datetime(print_greeting)
func()
処理の順番として
1.print_datetime関数の引数fに
print_greeting関数オブジェクトを渡し
print_datetime関数を呼び出す
2.wrapper関数をprint_datetime関数内で定義
3.wrapper関数をオブジェクトとして返しfuncに格納
4.func()でwrapper関数を実行
出力結果は
メインの名前の入力と挨拶の
処理の間に処理を行った時間が
デコレートされています
デコレーターを実装する
「@ デコレーター名」を追加して
上記のコードを書き替えます
import datetime
def print_datetime(f):
# print_datetime内でwrapper関数が定義されている
def wrapper():
print(f"start: {datetime.datetime.now()}")
f()
print(f"end: {datetime.datetime.now()}")
# wrapper関数をオブジェクトとして返す
return wrapper
@print_datetime
def print_greeting():
s = input("あなたのお名前は? : ")
print(f"こんにちわ {s} さん")
print_greeting()
完成しました
print_greetingは
print_datetimeでデコレーション
されたことになりました
出力結果は以下のようになります
デコレーターは
メインの処理を
変えずに
様々な機能を
装飾していく
イメージなんだね!