PyCraft
进阶

装饰器(Decorator)

用 @ 给函数“加一层能力”:缓存、计时、日志、权限校验

装饰器(Decorator)

装饰器可以理解为:不改原函数代码,在外面“包一层”,给函数增加额外能力(比如日志、计时、缓存、权限判断)。

它之所以能做到,是因为 Python 里函数也是对象:能作为参数传递、也能作为返回值返回。


最小例子:给函数加日志

装饰器本质是一个函数:接收一个函数 func,返回一个新函数 wrapper

加载代码编辑器中…

等价写法(更直观):

加载代码编辑器中…

functools.wraps:保留函数名与注释(推荐)

如果不做处理,装饰后函数的 __name____doc__ 会变成 wrapper 的信息。用 functools.wraps 可以保留原信息(很多库/工具依赖这个)。

加载代码编辑器中…

带参数的装饰器:装饰器工厂

想写 @log_call(prefix="DEBUG") 这种形式,需要多一层:外层先接收装饰器参数,返回真正的装饰器。

加载代码编辑器中…

多个装饰器的顺序(常见坑)

写成:

@A
@B
def f(): ...

等价于:

f = A(B(f))

也就是 离函数更近的 @B 先应用,外层再套 @A

加载代码编辑器中…

LeetCode 高价值用法:lru_cache 记忆化

递归 DFS / 状态 DP 很常见:同一个状态会重复算。用 functools.lru_cache 可以把结果缓存起来,显著提速。

加载代码编辑器中…

二维/多参数状态也一样:

加载代码编辑器中…

小结

  • 装饰器:接收函数、返回“包了一层的新函数”,常用 *args, **kwargs 做通用转发。
  • @wraps:强烈建议加,保留原函数元信息。
  • 带参数装饰器:多一层“装饰器工厂”。
  • 刷题常用@lru_cache(None) 做记忆化,提升递归 DP/DFS 性能。