デコレーター_3(Python_40) (original) (raw)
この連載では、Pythonについて色々な形で再学習に取り組んでいます。前回の記事はこちらになります。
前回は、デコレーターの意味について学びました。色々な引数のパターンに対応するために、デコレーター関数の中にラッパー関数を持たせます。
今回はデコレーターの使用例、応用例を見ていきます。
所用時間の確認
関数を開発しているときに、実行にかかる時間を測定したい場面があります。そんな時にデコレーターを使用すれば、関数本体に手を加えることなく所用時間を測ることができます。
import time
def timer_deco(func): def wrap(*args, **kwargs): print(func.name) start_time = time.time() result = func(*args, **kwargs) end_time = time.time() print(f"所要時間: {end_time - start_time} 秒") return result return wrap
@timer_deco def test_func(): print("test_func処理開始") time.sleep(2)
test_func()
test_func
test_func処理開始
所要時間: 2.000764846801758 秒
開発が完了したら、関数の前に記述しているデコレーターを削除すればいいのです。
作業ログ
関数が実行される際にログ(記録)を取りたい場合があります。関数が1つだけの場合は該当の関数に記述すればいいのですが、複数の関数に対して同様のログを取りたい場合は、関数毎にコードを書くのは非効率です。このような処理の場合、デコレーターの使用が有効です。
import datetime
def log_deco(func): def wrap(*args, **kwargs): result = func(*args, **kwargs) print(datetime.datetime.now() , end = " : 関数 ") print(func.name , end = ": 引数 ") print(*args, **kwargs, end = ": 返り値 : ") print(result) return return wrap
@log_deco def func_1(): pass
@log_deco def func_2(a,b): return a * b
@log_deco def func_3(val_1,val_2 = 2): return val_1 * val_2
func_1() func_2(3, 4) func_3(3)
2024-09-20 09:59:05.340213 : 関数 func_1: 引数 : 返り値 : None
2024-09-20 09:59:05.340213 : 関数 func_2: 引数 3 4: 返り値 : 12
2024-09-20 09:59:05.340213 : 関数 func_3: 引数 3: 返り値 : 6
この例では標準出力に出力していますが、実際にはファイルに出力することになるでしょう。色々な引数のパターンに対応できています。
条件チェック
特定の条件を満たした対象のみ、関数の使用を許可したい場合があります。そんな関数が複数ある場合、デコレーターで条件チェック機能をまとめて実装すると効率的です。
def rank_check(func): def wrap(user): if user['rank'] in ["A","B"]: return func(user) else: print(f"{user['name']}さんは、使用できません") return wrap
@rank_check def say_hello(user): print(f"{user['name']}さん、こんにちは")
user_1 = {"name": "Alice", "rank": "A"} user_2 = {"name": "Tom", "rank": "B"} user_3 = {"name": "Bob", "rank": "C"}
say_hello(user_1) say_hello(user_2) say_hello(user_3)
Aliceさん、こんにちは
Tomさん、こんにちは
Bobさんは、使用できません
この例ではランクがAかBのメンバーのみ、関数say_helloを使用できます。
クラスのインスタンスメソッドへの適用
クラスのインスタンスメソッドにも、デコレーターを使用できます。
def deco(func): def wrap(self): print(f"{func.name}が呼ばれました") return func(self) return wrap
class MyClass: @deco def greet(self): print("こんにちは")
obj = MyClass() obj.greet()
greetが呼ばれました
こんにちは
次回もデコレーター(エラー対応)
いかがでしょうか。デコレーターは色々な使い道が考えられますね。次回はデコレーターを使ったエラー対応について考えてみます。お楽しみに!!