今天我们来看看python自带的functools模块中三个实用的缓存装饰器:cache、cached_property和lru_cache。它们专门用来缓存高耗时计算结果,不管是加速递归算法,还是简化类属性计算,都能轻松解决。cache是一个轻量级的结果记忆装饰器,会自动缓存函数的返回值,相同入参再次调用时,直接返回缓存结果,不用重复计算。我们来看个简单实例:from functools import cache# 只需要加一个装饰器,自动开启缓存@cachedef factorial(n): # 递归计算阶乘 return n * factorial(n-1) if n else 1# 第一次调用:真实计算print(factorial(10)) # 输出:3628800# 第二次调用:直接读缓存,0 计算耗时print(factorial(10)) # 输出:3628800
它的使用很简单,但是要注意缓存大小,避免内存占用过高。cached_property专门给类方法使用,会把方法变成一个属性,第一次访问时计算一次,后续则会从缓存读取,这是类懒加载的利器。同样我们从代码实例来理解:from functools import cached_propertyclass Circle: def __init__(self, radius): self.radius = radius # 装饰后变成属性,只计算一次 @cached_property def area(self): print("Computing area") # 只会打印一次 return 3.14159 * self.radius ** 2c = Circle(5)# 第一次:执行计算print(c.area)# 输出:# Computing area# 78.53975# 第二次:直接返回缓存,不执行方法print(c.area) # 输出:78.53975
可以自己验证它的懒加载方式,每个实例只会计算一次,节省CPU,当然也要注意,缓存值可以被櫭,只适合不可变数据。看过了前两种,接下来我们看看lru_cache,它是最强大的缓存装饰器,支持LRU淘汰策略,可限制缓存大小,线程安全,还自带调试工具。我们也来看看实例代码:from functools import lru_cache# 限制最多缓存 32 条结果@lru_cache(maxsize=32)def fib(n): if n < 2: return n return fib(n-1) + fib(n-2)print(fib(10)) # 输出:55# 查看缓存状态:命中数/未命中数/最大容量/当前容量print(fib.cache_info())# 输出:CacheInfo(hits=8, misses=11, maxsize=32, currsize=11)
它的优点是可配置大小,平衡内存性能,同时还是线程安全的,多线程场景可以随意使用。总结一下,简单的函数快速缓存使用@cache;对于类的耗时属性中只需要计算一次的使用@cached_property;而在多线程中需要控制内存可以使用@lru_cached。当然,说得再多也不如自己亲自尝试一下。