0. 标题
Python专家编程系列: 3. 善用装饰器使代码提高一个层次(Powerful Python Decorator)
代码语言:txt复制作者: quantgalaxy@outlook.com
blog: https://blog.csdn.net/quant_galaxy
欢迎交流
1. 常用的装饰器
1.1 cache
请注意,它仅适用于 Python >= 3.9。
这样就可以缓存以前的值并重复使用,而不是重新计算。
代码语言:python代码运行次数:0复制from functools import cache
@cache
def factorial(n):
return n * factorial(n-1) if n else 1
print(factorial(10))
Output:
代码语言:shell复制3628800
这个装饰器,把factorial的每个步骤的值都记录下来了,在递归的过程中,就可以重复使用,并且在下次访问中也可以重复使用。
1.2 lru_cache
和cache类似,不过有一个maxsize参数,用来设置缓存的最大数量,避免内存膨胀。
当缓存已满并且需要存储新结果时,最近最少使用的结果将从缓存中逐出以为新结果腾出空间。这称为最近最少使用 (LRU) 策略。
默认情况下,maxsize 设置为 128。如果将其设置为 None,如我们的示例,LRU 功能将被禁用,并且缓存可以无限增长。
代码语言:python代码运行次数:0复制from functools import lru_cache
import time
@lru_cache(maxsize=None)
def fibonacci(n):
if n < 2:
return n
return fibonacci(n - 1) fibonacci(n - 2)
start_time = time.perf_counter()
print(fibonacci(30))
end_time = time.perf_counter()
print(f"The execution time: {end_time - start_time:.8f} seconds")
# The execution time: 0.000023434 seconds
1.3 wraps
@wraps修饰器用于在修饰函数或方法后保留其元数据。
这对于调试、内省和文档目的非常有用。
比如下面这个,加入调试信息的使用:
代码语言:python代码运行次数:0复制from functools import wraps
def debug(func):
@wraps(func)
def wrapper(*args, **kwargs):
print(f"Calling {func.__name__} with args={args} kwargs={kwargs}")
result = func(*args, **kwargs)
print(f"{func.__name__} returned {result}")
return result
return wrapper
@debug
def my_function(x, y):
return x y
my_function(1, 2) # prints "Calling my_function with args=(1, 2) kwargs={}" and "my_function returned 3"
下面这个例子展示了使用这个装饰器后,原函数的内置变量都被保留了下来:
代码语言:python代码运行次数:0复制from functools import wraps
def my_decorator(func):
@wraps(func)
def wrapper(*args, **kwargs):
# do something before
result = func(*args, **kwargs)
# do something after
return result
return wrapper
@my_decorator
def my_function():
"""My function docstring"""
pass
print(my_function.__name__) # my_function
print(my_function.__doc__) # My function docstring
代码语言:txt复制作者: quantgalaxy@outlook.com
blog: https://blog.csdn.net/quant_galaxy
欢迎交流
1.4 timeit
@timeit装饰器用于测量函数的执行时间并将其打印到控制台。
这对于分析代码和查找性能瓶颈非常有用。
代码语言:python代码运行次数:0复制import time
from functools import wraps
def timeit(func):
@wraps(func)
def wrapper(*args, **kwargs):
start = time.perf_counter()
result = func(*args, **kwargs)
end = time.perf_counter()
print(f'{func.__name__} took {end - start:.6f} seconds to complete')
return result
return wrapper
@timeit
def process_data():
time.sleep(1)
process_data()
# process_data took 1.000012 seconds to complete
1.5 contextmanager
@contextmanager装饰器用于定义一个函数,该函数可用作带有 with 语句的上下文管理器。
这对于自动获取和释放资源(如文件句柄或锁)非常有用。
代码语言:python代码运行次数:0复制from contextlib import contextmanager
@contextmanager
def my_context_manager():
# acquire resource
yield
# release resource
with my_context_manager():
# use resource
pass
1.6 atexit.register
atexit 模块的 @register 装饰器可以让我们在 Python 解释器退出时执行一个函数。
这个装饰器对于执行最终任务非常有用,例如释放资源或只是打印调试信息:
代码语言:python代码运行次数:0复制import atexit
@atexit.register
def goodbye():
print("Bye bye!")
print("Hello Tim!")
Output:
代码语言:shell复制Hello Tim!
Bye bye!
2. 作者信息
代码语言:txt复制作者: quantgalaxy@outlook.com
blog: https://blog.csdn.net/quant_galaxy
欢迎交流