如何在不泄漏内存的情况下在类内部使用 functools.lru_cache
?
在下面的最小示例中, foo
实例不会被释放,尽管超出范围并且没有引用者(除了 lru_cache
)。
from functools import lru_cache
class BigClass:
pass
class Foo:
def __init__(self):
self.big = BigClass()
@lru_cache(maxsize=16)
def cached_method(self, x):
return x + 5
def fun():
foo = Foo()
print(foo.cached_method(10))
print(foo.cached_method(10)) # use cache
return 'something'
fun()
但是 foo
因此 foo.big
(a BigClass
) 还活着
import gc; gc.collect() # collect garbage
len([obj for obj in gc.get_objects() if isinstance(obj, Foo)]) # is 1
这意味着 Foo
/ BigClass
实例仍然驻留在内存中。即使删除 Foo
(del Foo
) 也不会释放它们。
为什么 lru_cache
保留实例?缓存不使用一些散列而不是实际对象吗?
在类中使用 lru_cache
的推荐方法是什么?
我知道有两种解决方法: 使用每个实例缓存 或 使缓存忽略对象(但这可能会导致错误的结果)
原文由 televator 发布,翻译遵循 CC BY-SA 4.0 许可协议
这不是最干净的解决方案,但它对程序员来说是完全透明的:
它采用与
lru_cache
完全相同的参数,并且工作方式完全相同。但是它永远不会通过self
到lru_cache
而是使用每个实例lru_cache
。