Quantcast
Channel: HiroCom777の学習記録
Viewing all articles
Browse latest Browse all 90

デコレーター_3(Python_40)

$
0
0

この連載では、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が呼ばれました
# こんにちは

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

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

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


Viewing all articles
Browse latest Browse all 90

Trending Articles