2026-10-27 12:42:31
Python装饰器的高级用法中,functools模块提供了多种工具来实现优雅的函数包装与性能优化。以下是具体技巧和示例:
1. 使用functools.wraps保留函数元信息装饰器会修改被装饰函数的元信息(如__name__、__doc__),而functools.wraps可以保留这些信息。
from functools import wrapsdef better_log(func): @wraps(func) # 保留原函数的元信息 def wrapper(*args, kwargs): print(f"调用了函数: {func.__name__}") return func(*args, kwargs) return wrapper@better_logdef greet(name): """打个招呼""" return f"你好,{name}!"print(greet.__name__) # 输出: greetprint(greet.__doc__) # 输出: 打个招呼2. 带参数的装饰器通过嵌套函数实现带参数的装饰器,灵活控制装饰行为。
from functools import wrapsimport timedef retry(max_tries=3, delay=1): def decorator(func): @wraps(func) def wrapper(*args, kwargs): tries = 0 while tries < max_tries: try: return func(*args, kwargs) except Exception as e: tries += 1 if tries == max_tries: raise e print(f"重试第{tries}次...") time.sleep(delay) return None return wrapper return decorator@retry(max_tries=2, delay=0.5)def flakey_function(): import random if random.random() < 0.7: raise ValueError("糟糕,出错了!") return "成功啦!"3. functools.lru_cache性能优化通过缓存函数结果提升递归或重复调用的性能。
from functools import lru_cache@lru_cache(maxsize=128) # 缓存最近128次调用的结果def fibonacci(n): if n < 2: return n return fibonacci(n-1) + fibonacci(n-2)# 测试性能import timestart = time.time()print(fibonacci(100)) # 直接计算,无缓存时极慢print(f"用时: {time.time() - start}秒")注意:maxsize=None表示无限缓存,但可能增加内存消耗。
4. 装饰器链式调用多个装饰器可以叠加使用,执行顺序从内到外。
def bold(func): @wraps(func) def wrapper(): return f"<b>{func()}</b>" return wrapperdef italic(func): @wraps(func) def wrapper(): return f"<i>{func()}</i>" return wrapper@bold@italicdef hello(): return "Python装饰器真好玩"print(hello()) # 输出: <b><i>Python装饰器真好玩</i></b>5. 临时禁用装饰器调试时可通过注释@快速禁用装饰器,无需修改装饰器代码。
# @better_log # 临时禁用def greet(name): return f"你好,{name}!"关键点总结合理使用这些技巧,可以显著提升代码的优雅性和性能,但需避免过度装饰导致逻辑复杂化。