Python专家编程系列: 3. 善用装饰器使代码提高一个层次(Powerful Python Decorator)
作者: quantgalaxy@outlook.com
blog: https://blog.csdn.net/quant_galaxy
欢迎交流
请注意,它仅适用于 Python >= 3.9。
这样就可以缓存以前的值并重复使用,而不是重新计算。
from functools import cache
@cache
def factorial(n):
return n * factorial(n-1) if n else 1
print(factorial(10))
Output:
3628800
这个装饰器,把factorial的每个步骤的值都记录下来了,在递归的过程中,就可以重复使用,并且在下次访问中也可以重复使用。
和cache类似,不过有一个maxsize参数,用来设置缓存的最大数量,避免内存膨胀。
当缓存已满并且需要存储新结果时,最近最少使用的结果将从缓存中逐出以为新结果腾出空间。这称为最近最少使用 (LRU) 策略。
默认情况下,maxsize 设置为 128。如果将其设置为 None,如我们的示例,LRU 功能将被禁用,并且缓存可以无限增长。
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
@wraps修饰器用于在修饰函数或方法后保留其元数据。
这对于调试、内省和文档目的非常有用。
比如下面这个,加入调试信息的使用:
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"
下面这个例子展示了使用这个装饰器后,原函数的内置变量都被保留了下来:
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
作者: quantgalaxy@outlook.com
blog: https://blog.csdn.net/quant_galaxy
欢迎交流
@timeit装饰器用于测量函数的执行时间并将其打印到控制台。
这对于分析代码和查找性能瓶颈非常有用。
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
@contextmanager装饰器用于定义一个函数,该函数可用作带有 with 语句的上下文管理器。
这对于自动获取和释放资源(如文件句柄或锁)非常有用。
from contextlib import contextmanager
@contextmanager
def my_context_manager():
# acquire resource
yield
# release resource
with my_context_manager():
# use resource
pass
atexit 模块的 @register 装饰器可以让我们在 Python 解释器退出时执行一个函数。
这个装饰器对于执行最终任务非常有用,例如释放资源或只是打印调试信息:
import atexit
@atexit.register
def goodbye():
print("Bye bye!")
print("Hello Tim!")
Output:
Hello Tim!
Bye bye!
作者: quantgalaxy@outlook.com
blog: https://blog.csdn.net/quant_galaxy
欢迎交流
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。