1. 裝飾器基礎
1.1 什么是裝飾器?
????????裝飾器本質上是一個 Python 函數,它可以讓其他函數在不需要做任何代碼變動的前提下增加額外功能。裝飾器的返回值也是一個函數對象。
1.2 語法糖:@ 符號
????????Python?提供了 @ 符號作為裝飾器的語法糖,使得裝飾器的使用更加簡潔明了。
2. 創建簡單裝飾器
????????下面是一個簡單的裝飾器示例,用于記錄函數執行時間:
import timedef timer_decorator(func):def wrapper(*args, **kwargs):start_time = time.time()result = func(*args, **kwargs)end_time = time.time()print(f"{func.__name__} executed in {end_time - start_time:.4f} seconds")return resultreturn wrapper# 使用裝飾器
@timer_decorator
def slow_function():time.sleep(2)print("Function executed")slow_function()
???????在這個例子中,timer_decorator 是一個裝飾器函數,它接受一個函數作為參數,并返回一個新的函數 wrapper。wrapper 函數在執行原函數前后記錄時間,并打印執行時間。
3. 裝飾器的工作原理
????????當使用 @decorator 語法糖時,Python 實際上做了以下幾件事:
- 調用 decorator 函數,將目標函數作為參數傳入。
- 裝飾器函數返回一個新的函數(通常是包裝函數)。
- 將目標函數的引用替換為新函數的引用。
????????因此,@timer_decorator 等價于 slow_function = timer_decorator(slow_function)。
4. 帶參數的裝飾器
????????有時候,我們可能需要為裝飾器本身傳遞參數。這可以通過再嵌套一層函數來實現:
def repeat_decorator(times):def decorator(func):def wrapper(*args, **kwargs):for _ in range(times):result = func(*args, **kwargs)return resultreturn wrapperreturn decorator# 使用帶參數的裝飾器
@repeat_decorator(3)
def say_hello():print("Hello, World!")say_hello()
????????在這個例子中,repeat_decorator 是一個返回裝飾器的函數,它接受一個參數 times,表示目標函數需要被執行的次數。
5. 保留原函數的元數據
????????使用裝飾器后,原函數的元數據(如函數名、文檔字符串等)可能會丟失。為了保留這些元數據,可以使用 functools 模塊中的 wraps 裝飾器:
from functools import wrapsdef my_decorator(func):@wraps(func)def wrapper(*args, **kwargs):print("Something is happening before the function is called.")result = func(*args, **kwargs)print("Something is happening after the function is called.")return resultreturn wrapper@my_decorator
def example_function():"""This is an example function."""print("Hello from example_function!")print(example_function.__name__) # 輸出: example_function
print(example_function.__doc__) # 輸出: This is an example function.
6. 裝飾器的應用場景
- 日志記錄:記錄函數的調用時間、參數和返回值。
- 性能分析:測量函數的執行時間,找出性能瓶頸。
- 訪問控制:根據用戶權限決定是否允許執行函數。
- 事務處理:在函數執行前后開啟和提交事務。
- 緩存:緩存函數的計算結果,避免重復計算。
????????裝飾器是 Python 中一個非常強大的特性,它允許我們以一種優雅且靈活的方式擴展函數的功能。通過掌握裝飾器的使用,我們可以編寫出更加模塊化、可重用和易于維護的代碼。希望本文能夠幫助你更好地理解和應用 Python 中的裝飾器。