什么是装饰器
包装器,英文wrapper,一种函数,能够作用于别的函数从而给被作用的函数添加新功能,或是修改其行为。包装器通常以装饰器(英文是decorator)的形式实现,装饰器将另一个函数作为输入,并对功能做一些改进。
包装器可以被应用于很多场景:
- 功能扩展:添加一些特征(features),比如打印日志(logging),评估性能或者缓存。
- 代码复用:包装器无疑可以被应用到很多地方,既能防止代码重复,又能确保跨组件的一致行为。
- 行为修改:我们可以解释输入参数,比如,在不需要写很多assert语句的前提下避免许多输入变量。
例子🍒来了
下面的例子会说服你相信装饰器是日常工作中不可或缺的。
1 - Timer
timer能够用来计算和打印一个函数的执行时间。
import timedef timer(func):def wrapper(*args, **kwargs):# start the timerstart_time = time.time()# call the decorated functionresult = func(*args, **kwargs)# remeasure the timeend_time = time.time()# compute the elapsed time and print itexecution_time = end_time - start_timeprint(f"Execution time: {execution_time} seconds")# return the result of the decorated function executionreturn result# return reference to the wrapper functionreturn wrapper
定义了一个名为timer的函数,timer接收func为参数,证明其是一个装饰器函数。在timer的内部,定一个名为wrapper的函数,想要传给被装饰函数的参数由wrapper来接收。
在wrapper内部,用提供的参数调用被装饰函数,即
result = func(*args, **kwargs)
最终,wrapper返回了被装饰函数的执行。装饰器函数(timer)应当返回wrapper的索引。
我们选一个被装饰函数来用一下装饰器
@timer
def train_model():print("Starting the model training function...")# simulate a function execution by pausing the program for 5 secondstime.sleep(5) print("Model training completed!")train_model()
输出为
Starting the model training function...
Model training completed!
Execution time: 5.0018792152404785 seconds
2 - Debugger
未完待续
3 - Retry
如果你的函数涉及到网络的处理或API的调用,那么装饰器retry将非常有用。retry可以让一个函数重复执行固定的次数,同时能设置次数之间的延迟。
import timedef retry(max_attempts, delay=1):def decorator(func):def wrapper(*args, **kwargs):attempts = 0while attempts < max_attempts:try:return func(*args, **kwargs)except Exception as e:attempts += 1print(f"Attempt {attempts} failed: {e}")time.sleep(delay)print(f"Function failed after {max_attempts} attempts")return wrapperreturn decorator
用法
@retry(max_attempts=3, delay=2)
def fetch_data(url):print("Fetching the data..")# raise timeout error to simulate a server not responding..raise TimeoutError("Server is not responding.")
fetch_data("https://example.com/data") # Retries 3 times with a 2-second delay between attempts
输出
Fetching the data..
Attempt 1 failed: Server is not responding.
Fetching the data..
Attempt 2 failed: Server is not responding.
Fetching the data..
Attempt 3 failed: Server is not responding.
Function failed after 3 attempts
原文链接
Five Python Decorators That Can Reduce Your Code By Half