裝飾器(Decorators)
定義:
裝飾器是一個函數,它可以將另一個函數作為參數,並在不永久修改該函數的情況下擴展或改變其行為。裝飾器提供了一種靈活的方法來為函數或方法添加功能。
用途:
裝飾器常用於日誌記錄、訪問控制、快取(memoization)等功能。它們可以應用於任何函數,並且通常以一種簡潔且可讀的方式增強功能。
以下舉例一個簡單的例子:simple_decorator(func),func指的是想要裝飾的function,下面的例子是say_hello function,在simple_decorator額外定義wrapper function是python定義的使用方式,名稱不一定要教wrapper。wrapper內的功能可以自由定義,比如下面的例子就是,在執行say_hello前因為前面識別到@simple_decorator,所以變成執行裝飾器(Decorator),而執行內容則是wrapper函數,可以看到會先print "Before function execution" -> say_hello -> print "Afterfunction execution"
def simple_decorator(func): def wrapper(): print("Before function execution.") func() print("After function execution") return wrapper# must place at a function which you want to decorate@simple_decoratordef say_hello(): print("Hello!")say_hello() |
執行結果則會如下所示,可以看到@simple_decorator用在裝飾say_hello function。
Before function execution.Hello!After function execution |
經過簡單的介紹,可以了解到裝飾器(Decorator)對於function的可擴充性非常大,由於我們不需要更改原本函數即可位原本函數增加功能,這對於大型專案非常有利。以下會再多做幾的簡單的裝飾器用法。
- 計算函數執行時間: 我們可以用裝飾器來讓原本函數得到計算時間的功能,方法如下
def time_decorator(func): def wrapper(): start_time = time.time() result = func() end_time = time.time() print(f"Function execution time: {end_time - start_time}") return result return wrapper @time_decoratordef exec_func(): time.sleep(2) print("Function finished!") |
- 驗證參數: 下面的例子是,可以驗證傳入參數是否為正數square_root(-1),帶入-1,這時顯示結果會變成ValueError: The number must be positive
def validate_positive(func): def wrapper(x): if x <= 0: raise ValueError("The number must be positive") return func(x) return wrapper @validate_positivedef square_root(x): return x**0.5print(square_root(-1)) |
- 裝飾器帶參數: 若是裝飾器想要帶入參數,可以用以下作法,這時需要一個裝飾器工廠 (Decorator Factory)來接受參數,通常是用來動態配置裝飾器使用本身並非裝飾器。下面這個例子,角色分別為, conditional_decorator = 裝飾器工廠, decorator = 裝飾器, wrapper = 包裝函數。常見用法就是可以控制函數本身能不能被啟動,比如should_run = False表示表示我不想啟動greet()這個function。因此最後執行結果為Function will not run
def conditional_decorator(should_run=True): def decorator(func): def wrapper(*args, **kwargs): if should_run: return func(*args, **kwargs) else: print("Function will not run") return wrapper return decorator @conditional_decorator(should_run=False)def greet(): print("Hello!")greet() |
- 多個裝飾器: 這個例子展示了如何使用多個裝飾器來裝飾一個函數,並且每個裝飾器會依序執行,由上至下依序執行裝飾器。decorator_one -> decorator_two
def decorator_one(func): def wrapper(): print("Decorator One") func() return wrapper def decorator_two(func): def wrapper(): print("Decorator Two") func() return wrapper @decorator_one@decorator_twodef greet(): print("Hello")greet() |
- 裝飾器實現快取(cache): 這個裝飾器用來cached函數的結果,這樣如果相同的參數再次調用,則直接返回cached的結果,而不再執行函數。因為我們創建了cache字典,來cache住結果,在wrapper函數中,我們直接查找cache dictionary,如果有存在裡面的話會直接返回cache值。實際上我目前還沒碰過比較大型的專案,所以這類用法還沒有很熟悉,不過看起來應該使用起來好處滿多的。
def cache_decorator(func): cache = {} def wrapper(x): if x in cache: return cache[x] result = func(x) cache[x] = result return result return wrapper@cache_decoratordef expensive_compute(x): print(f"Compute {x}...") return x * xprint(expensive_compute(4))print(expensive_compute(4)) |
以上就是裝飾器(Decorator),自己研究加上一些網路資料所的知的用法,如果有更多的使用方式歡迎留言告訴我
文章標籤
全站熱搜
