进阶
装饰器(Decorator)
用 @ 给函数“加一层能力”:缓存、计时、日志、权限校验
装饰器(Decorator)
装饰器可以理解为:不改原函数代码,在外面“包一层”,给函数增加额外能力(比如日志、计时、缓存、权限判断)。
它之所以能做到,是因为 Python 里函数也是对象:能作为参数传递、也能作为返回值返回。
最小例子:给函数加日志
装饰器本质是一个函数:接收一个函数 func,返回一个新函数 wrapper。
加载代码编辑器中…
等价写法(更直观):
加载代码编辑器中…
functools.wraps:保留函数名与注释(推荐)
如果不做处理,装饰后函数的 __name__、__doc__ 会变成 wrapper 的信息。用 functools.wraps 可以保留原信息(很多库/工具依赖这个)。
加载代码编辑器中…
带参数的装饰器:装饰器工厂
想写 @log_call(prefix="DEBUG") 这种形式,需要多一层:外层先接收装饰器参数,返回真正的装饰器。
加载代码编辑器中…
多个装饰器的顺序(常见坑)
写成:
等价于:
也就是 离函数更近的 @B 先应用,外层再套 @A。
加载代码编辑器中…
LeetCode 高价值用法:lru_cache 记忆化
递归 DFS / 状态 DP 很常见:同一个状态会重复算。用 functools.lru_cache 可以把结果缓存起来,显著提速。
加载代码编辑器中…
二维/多参数状态也一样:
加载代码编辑器中…
小结
- 装饰器:接收函数、返回“包了一层的新函数”,常用
*args, **kwargs做通用转发。 @wraps:强烈建议加,保留原函数元信息。- 带参数装饰器:多一层“装饰器工厂”。
- 刷题常用:
@lru_cache(None)做记忆化,提升递归 DP/DFS 性能。