我有一些实例化的对象非常慢。它们表示从外部源(如YAML文件)加载的数据,并且加载大型YAML文件很慢(我不知道为什么)。
我知道这些对象取决于一些外部因素:
理想情况下,如果外部因素相同,我想要一个透明的非样板方法来缓存这些对象:
@cache(depfiles=('foo',), depvars=(os.environ['FOO'],))
class Foo():
def __init__(*args, **kwargs):
with open('foo') as fd:
self.foo = fd.read()
self.FOO = os.environ['FOO']
self.args = args
self.kwargs = kwargs
主要思想是我第一次实例化Foo
时,会使用对象的内容创建缓存文件,然后在下次实例化它时(在另一个Python会话中),缓存文件将是仅在依赖项和参数均未更改时使用。
到目前为止,我找到的解决方案基于shelve
:
import shelve
class Foo(object):
_cached = False
def __new__(cls, *args, **kwargs):
cache = shelve.open('cache')
cache_foo = cache.get(cls.__name__)
if isinstance(cache_foo, Foo):
cache_foo._cached = True
return cache_foo
self = super(Foo, cls).__new__(cls, *args, **kwargs)
return self
def __init__(self, *args, **kwargs):
if self._cached:
return
time.sleep(2) # Lots of work
self.answer = 42
cache = shelve.open('cache')
cache[self.__class__.__name__] = self
cache.sync()
它完美无缺,但它太样板,并没有涵盖所有情况:
是否有任何 native 解决方案在Python中实现类似的行为?
答案 0 :(得分:1)
Python 3提供functools.lru_cache()
装饰器来提供可调用的memoization,但我认为你要求在你的应用程序的多次运行中保留缓存,到那时你有各种各样的不同要求。 '不太可能找到'一刀切'的解决方案。
如果您自己的答案适合您,请使用它。就“太多样板文件”而言,我会将缓存提取到一个单独的mixin类中:Foo
中__new__
的第一个引用在任何情况下都可能应该是cls
。您可以使用__qualname__
属性而不是cls.__name__
来减少类名冲突的可能性(假设Python 3.3或更高版本)。