Kev*_*ini 11
首先,lru_cache
是python语言本身提供的装饰器,如python 3.4; cached_property
是一个专门从django提供的装饰器.话虽如此,他们是相似的.
lru_cache
在函数式编程中特别有用.它的作用是使用一组参数保存函数调用的结果.当lru_cache
使用相同的参数多次调用装饰的函数时,装饰器将只返回函数结果的缓存结果.这采用了一种称为动态编程的编程方法,更具体地说,是存储器.使用这些方法,您可以大大加快重复调用计算成本高昂的函数的代码.
Python还提供了另一个类似的装饰器lfu_cache
.这两个装饰器都实现了memoization,但是使用了不同的替换策略.lru_cache
(最近最少使用的)将填充它的缓存并且必须在下一个修饰函数调用期间踢出一些东西.此替换策略规定最近最少使用的条目将被新数据替换.lfu_cache
(最不常用)指示替换基于最少使用哪些条目而发生.
cached_property
是类似lru_cache
的,因为它昂贵缓存函数调用的结果的意义.这里唯一的区别是它只能用于方法,这意味着函数属于一个对象.此外,它们只能用于除了之外没有其他参数的方法self
.你会特别想在django开发期间使用它来获取命中数据库的类的方法.在Django文档提到其上有一个属性方法的模型类的使用friends
.这个方法可能会命中数据库来收集一组人,他们是该实例的朋友Person
.因为对数据库的调用很昂贵,所以我们希望缓存该结果以供以后使用.
Con*_*tor 6
一个主要的区别是这lru_cache
将使缓存中的对象保持活动状态,这可能会导致内存泄漏,尤其是在应用 lru_cache 的实例很大的情况下(参见:https ://bugs.python./issue19859 )
class A:
@property
@functools.lru_cache(maxsize=None)
def x(self):
return 123
for _ in range(100):
A().x # Call lru_cache on 100 different `A` instances
# The instances of `A()` are never garbage-collected:
assert A.x.fget.cache_info().currsize == 100
有了cached_property
,就没有缓存,所以没有内存泄漏。
class B:
@functools.cached_property
def x(self):
return 123
b = B()
print(vars(b)) # {}
b.x
print(vars(b)) # {'x': 123}
del b # b is garbage-collected
另一个区别是@property
只读而@cached_property
不是。 cache_property
允许写入属性参考 Python 文档
A().x = 123
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: can't set attribute
B().x = 123 # Works
这是由于@cached_property
正在替换属性,所以第二次调用b.x
绕过了B.x.get
描述符调用。
cached_property
如果您多次访问相同的属性,则性能会更高,而lru_cache
函数调用和属性查找会产生开销。请注意,差异仅在大量数字时可见。
A().x = 123
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: can't set attribute
Mar*_*riy 5
它们服务于不同的目的。
lru_cache
保存最近最少的使用 - 您应该指定maxsize
哪个区分您可以保存多少次函数计算。一旦超过这个数字,“最旧”的结果就会被丢弃,新的结果会被保存。
cached_property
只是计算结果并保存它。它不接受不同的参数lru_cache
(您可以将其视为lru_cache
maxsize = 1 且不带参数的对象类型)。
更多推荐
cached
发布评论