@cached_property和@lru_cache装饰器之间的区别

Rou*_*mar 7 python django

我是Django的新手.如果有人可以在Django中区分@cached_property和@lru_cache装饰器,那将会非常有用.我什么时候应该在Django中使用哪个装饰器.用例非常有用.谢谢.

Con*_*tor 12

  1. 一个主要区别是,lru_cache它将保持缓存中的对象处于活动状态,这可能会导致内存泄漏,特别是当应用 lru_cache 的实例很大时(请参阅: https: //bugs.python.org/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
Run Code Online (Sandbox Code Playgroud)

使用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
Run Code Online (Sandbox Code Playgroud)
  1. 另一个区别是@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
Run Code Online (Sandbox Code Playgroud)
B().x = 123  # Works
Run Code Online (Sandbox Code Playgroud)

这是由于@cached_property正在替换属性,因此第二次调用b.x绕过了B.x.get描述符调用。

  1. 在大多数情况下可能并不重要的另一个区别是,cached_property如果多次访问同一属性,则性能会更高,但lru_cache会产生函数调用和属性查找的开销。请注意,只有在数字很大时才能看到差异。
A().x = 123
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: can't set attribute
Run Code Online (Sandbox Code Playgroud)


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.因为对数据库的调用很昂贵,所以我们希望缓存该结果以供以后使用.

  • [`cached_property`](https://docs.python.org/3/library/functools.html?highlight=cached_property#functools.cached_property) 自 python 3.8 起包含在标准库中 (4认同)

Mar*_*riy 6

它们有不同的目的。

lru_cache保存最近最少的使用 - 您应该指定maxsize哪个可以区分您可以保存的函数的计算次数。一旦超过这个数字,“最旧”的结果将被丢弃,新的结果将被保存。

cached_property只是计算结果并保存它。它不接受参数lru_cache(您可以将其视为lru_cachemaxsize = 1 且不带参数的对象类型)。