デコレーター_3(Python_40) (original) (raw)

この連載では、Pythonについて色々な形で再学習に取り組んでいます。前回の記事はこちらになります。

hirocom777.hatenadiary.org

前回は、デコレーターの意味について学びました。色々な引数のパターンに対応するために、デコレーター関数の中にラッパー関数を持たせます。

今回はデコレーターの使用例、応用例を見ていきます。

所用時間の確認

関数を開発しているときに、実行にかかる時間を測定したい場面があります。そんな時にデコレーターを使用すれば、関数本体に手を加えることなく所用時間を測ることができます。

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が呼ばれました

こんにちは

次回もデコレーター(エラー対応)

いかがでしょうか。デコレーターは色々な使い道が考えられますね。次回はデコレーターを使ったエラー対応について考えてみます。お楽しみに!!

hirocom777.hatenadiary.org

Python再学習のまとめはこちら!!