functools模块通过提供lru_cache、partial和wraps等工具,可显著优化函数性能、实现参数灵活绑定及增强装饰器健壮性。以下是具体应用技巧:
1. lru_cache:通过缓存优化函数性能- 核心功能:实现备忘录模式(Memoization),缓存函数调用结果,避免重复计算。适用于参数不变的高耗时函数(如远程数据获取、递归算法)。
- 适用场景:
重复参数调用:如数据库查询、API请求等不频繁变动的数据获取场景。
递归算法优化:如斐波那契数列计算,避免重复子问题计算。
- 限制条件:
参数必须可哈希(如整数、字符串、元组),不可哈希类型(如列表、字典)需转换为可哈希形式。
需注意缓存内存占用,建议设置maxsize限制缓存大小(如@lru_cache(maxsize=128))。
- 示例代码:from functools import lru_cacheimport time@lru_cache(maxsize=None) # 无限制缓存def fetch_data(item_id: str) -> str: print(f"Fetching data for {item_id}...") time.sleep(2) # 模拟网络延迟 return f"Data for {item_id}"print(fetch_data("user_1")) # 第一次调用,耗时2秒print(fetch_data("user_1")) # 第二次调用,直接返回缓存结果@lru_cache(maxsize=128)def fibonacci(n): if n <= 1: return n return fibonacci(n-1) + fibonacci(n-2)print([fibonacci(n) for n in range(10)]) # 高效计算,避免重复递归
2. partial:实现函数参数的灵活绑定与复用3. wraps:增强装饰器的健壮性- 核心功能:在自定义装饰器中,保留被装饰函数的元数据(如__name__、__doc__),避免调试困难和工具失效。
- 问题场景:未使用wraps时,装饰器返回的包装函数会覆盖原始函数的元数据,导致调试信息混乱。
- 解决方案:用@wraps(func)装饰包装函数,自动复制原始函数的属性。
- 示例代码:from functools import wraps# 错误示例:丢失元数据def bad_decorator(func): def wrapper(*args, kwargs): print("Before call") return func(*args, kwargs) return wrapper@bad_decoratordef say_hello(name): """A friendly greeting.""" return f"Hello, {name}!"print(say_hello.__name__) # 输出 'wrapper'(错误)print(say_hello.__doc__) # 输出 None(错误)# 正确示例:使用 wraps 保留元数据def good_decorator(func): @wraps(func) def wrapper(*args, kwargs): print("Before call") return func(*args, kwargs) return wrapper@good_decoratordef say_goodbye(name): """A polite farewell.""" return f"Goodbye, {name}!"print(say_goodbye.__name__) # 输出 'say_goodbye'(正确)print(say_goodbye.__doc__) # 输出 'A polite farewell.'(正确)
总结- lru_cache:通过缓存优化性能,适用于重复参数调用的高耗时函数。
- partial:固定参数生成专用函数,提升代码复用性和可读性。
- wraps:确保装饰器不丢失元数据,是编写健壮装饰器的必备工具。掌握这些技巧可显著提升Python代码的效率、简洁性和可维护性。