@cache_property: 这个装饰器件 used to cache the result of a property method, preventing it from being recomputed each time it is accessed (meaning it will only be computed once and reused.). 这里举一个 Fibonacci 数列计算的简单例子:
from functools import cached_property
class Fibonacci:
def __init__(self, n):
self.n = n
@cached_property
def fibonacci(self):
print(f"Computing Fibonacci for {self.n}")
if self.n <= 1:
return self.n
else:
return Fibonacci(self.n - 1).fibonacci + Fibonacci(self.n - 2).fibonacci
# Usage
fib = Fibonacci(5)
print(fib.fibonacci) # First time, computation occurs
print()
print("Cached results:")
print(fib.fibonacci) # Second time, cached value
程序运行结果如下:
我们可以看到,当第二次调用fibonacci方法时,我们不再重新进行递归计算,而是直接调用缓存中存储的上一个结果。
@lru_cache:这个装饰器 is used to cache the results of expensive or frequently called functions. The acronym LRU stands for Least Recently Used. This means that the cache will store a limited number of results, and when the cache exceeds its size, it will discard the least recently used (oldest) results to make room for new ones.
This decorator is especially useful when you have a function that is repeatedly called with the same arguments and the results are predictable. By caching the results, you avoid recalculating them and improve the performance of your program.
from functools import lru_cache
@lru_cache(maxsize=128)
def expensive_function(x):
print(f"Computing expensive_function({x})")
return x * x
# Call the function with the same argument
print(expensive_function(5)) # Computes and caches result
print(expensive_function(5)) # Returns cached result (no computation)
print(expensive_function(10)) # Computes and caches result
程序运行结果如下:
@cached_property
和 @lru_cache
都是 Python 中用于缓存计算结果的装饰器,但它们的使用场景和功能有所不同。以下是它们的区别:
1. 目的和使用场景
-
@cached_property
:-
用于将一个方法转化为属性,并缓存该方法的计算结果。
-
它适用于那些不需要每次访问时重新计算的属性,比如计算复杂或昂贵的属性值,但计算结果不会改变。
-
通常用于对象的属性上,缓存第一次计算的结果。
使用场景: 如果你有一个对象的属性,计算该属性的值需要较多资源且该值不会变化,你可以使用
@cached_property
。 -
-
@lru_cache
:-
用于缓存函数的返回结果,特别适合那些经常被调用且参数相同的函数。
-
它采用 LRU(Least Recently Used) 缓存策略,即缓存最多一定数量的结果,当缓存满时,会删除最久未使用的条目。
-
通常用于 普通函数,尤其是递归函数或计算密集型函数,避免重复计算相同的输入。
使用场景: 如果你有一个计算密集型的函数,且该函数经常被调用并且具有相同的输入参数,使用
@lru_cache
可以提高性能。 -
2. 缓存机制
-
@cached_property
:-
只缓存 单一结果,当第一次访问属性时,计算并缓存该值。后续访问将直接返回缓存结果。
-
缓存无过期时间:一旦计算完成,结果一直有效,直到对象被销毁或显式清除缓存。
-
只缓存属性值,无法缓存函数的多次调用。
@lru_cache
: -
-
缓存函数 多次调用 的结果,尤其是在函数的输入参数相同的情况下。
-
它遵循 LRU(Least Recently Used) 策略:当缓存的条目超过
maxsize
设置时,会删除最久未使用的条目。 -
可以设置缓存大小,并且可以自动清除缓存(如果缓存超过设定的最大容量)。
3. 缓存清除与大小限制
-
@cached_property
:-
缓存无过期时间:结果一旦缓存,直到对象生命周期结束或者手动清除缓存才会过期。
-
它没有内建的缓存大小限制,所有的计算结果都会缓存。
-
-
@lru_cache
:-
缓存大小可以限制:通过
maxsize
参数限制缓存的条目数。缓存达到maxsize
后,LRU 算法会清除最不常用的缓存。 -
可以手动调用
cache_clear()
来清除缓存,或者通过cache_info()
查看缓存的状态。
-
4. 适用对象类型
-
@cached_property
:-
适用于对象的 属性,它将方法转化为只读属性。
-
通常用于不需要频繁更新的计算结果或数据。
-
-
@lru_cache
:-
适用于普通的 函数,尤其是递归函数或者需要频繁调用的函数。
-
用于任何需要缓存计算结果的场景,通常不局限于属性
-
5. 性能和适用场景
-
@cached_property
:-
适合用在需要 计算密集型属性 的类中。
-
适用于 只读属性,且属性的值在对象生命周期内不变。
-
-
@lru_cache
:-
适用于那些 重复计算 相同输入时的函数调用。
-
特别适用于 递归函数 或其他计算复杂的函数,可以显著提高性能。
-