英文:
When caching a class will all future instances refer to the exact same id as the original cached instance?
问题
我正在研究类的缓存工作方式,因为我认为这可能是我目前正在处理的代码中的一个问题的合理解决方案。
我一直在使用这个简单的类进行实例创建测试:
from functools import lru_cache
@lru_cache
class Foo:
def __init__(self, a: int):
self.a = a
self.b = sum(i**2 for i in range(self.a))
我看到的情况是,一切都按预期工作,当使用与已缓存的输入相同的输入时,初始化时间为0:
import datetime as dt
start_1 = dt.datetime.now()
bar = Foo(10_000)
elapsed_1 = (dt.datetime.now() - start_1) # 4008 ms
start_2 = dt.datetime.now()
baz = Foo(5_000)
elapsed_2 = (dt.datetime.now() - start_2) # 3003 ms
start_3 = dt.datetime.now()
boo = Foo(15_000)
elapsed_3 = (dt.datetime.now() - start_3) # 5002 ms
start_4 = dt.datetime.now()
bbb = Foo(10_000)
elapsed_4 = (dt.datetime.now() - start_4) # 0 ms
但在最后一个情况下,我看到没有创建新对象,只是引用了已存在的对象:
id(bar) == id(bbb) # True
显然,如果我们从类定义中删除 @lru_cache
,那么对于 a=10_000
的情况,我们会得到两个不同的对象,而此相同测试(上面的测试)将返回 False。
在缓存类时,新对象总是引用最初缓存的对象的行为是否有保证?
英文:
I was looking at how caching of classes works as I thought it would be a reasonable solution to one of the issues in the code I'm currently working on.
I've been testing the instance creation using this simple class:
from functools import lru_cache
@lru_cache
class Foo:
def __init__(self, a: int):
self.a = a
self.b = sum(i**2 for i in range(self.a))
What I see is that all is working as expected and when using the same input as the one already cached, the initialisation time is 0:
import datetime as dt
start_1 = dt.datetime.now()
bar = Foo(10_000)
elapsed_1 = (dt.datetime.now() - start_1) # 4008 ms
start_2 = dt.datetime.now()
baz = Foo(5_000)
elapsed_2 = (dt.datetime.now() - start_2) # 3003 ms
start_3 = dt.datetime.now()
boo = Foo(15_000)
elapsed_3 = (dt.datetime.now() - start_3) # 5002 ms
start_4 = dt.datetime.now()
bbb = Foo(10_000)
elapsed_4 = (dt.datetime.now() - start_4) # 0 ms
But in the last case I see that no new object is created, just a new reference to an already existing one:
id(bar) == id(bbb) # True
Obviously, if we remove @lru_cache
from class definition then we get two different objects for the case of a=10_000
and this same test (above) comes back as False.
Is this a guaranteed behaviour when caching classes that the new object will always reference the same originally cached id?
答案1
得分: 3
是的,当你使用functools.lru_cache
缓存一个类时,所有将来使用相同输入参数集的该类实例都将引用与原始缓存实例完全相同的对象。
这是因为lru_cache
将类的缓存实例存储在一个缓存字典中,以输入参数作为键。当请求使用相同输入参数的类的新实例时,lru_cache
会检查缓存字典,以查看是否已存在具有这些输入参数的实例。如果存在,它将返回该实例,否则它将创建一个新实例并将其添加到缓存字典中。
由于缓存字典在类的所有实例之间共享,所有具有相同输入参数的实例将引用内存中相同的对象,即缓存实例。
值得注意的是,这种行为不仅适用于在Python中使用lru_cache
缓存类,而且适用于内存中缓存对象的一般行为。如果在内存中缓存一个对象并使用相同的键检索它,你将始终获得内存中完全相同的对象实例。
英文:
Yes, when you cache a class using functools.lru_cache
, all future instances of that class with the same set of input arguments will refer to the exact same object as the original cached instance.
This is because lru_cache
stores the cached instances of the class in a cache dictionary, with the input arguments as the key. When a new instance of the class is requested with the same input arguments, lru_cache
checks the cache dictionary to see if an instance with those input arguments already exists. If it does, it returns that instance, otherwise it creates a new instance and adds it to the cache dictionary.
Since the cache dictionary is shared among all instances of the class, all instances with the same input arguments will reference the same object in memory, which is the cached instance.
It's worth noting that this behavior is not specific to caching classes with lru_cache
in Python, but is a general behavior of caching objects in memory. If you cache an object in memory and retrieve it using the same key, you will always get the exact same object instance in memory.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论