考虑以下几点:
@property
def name(self):
if not hasattr(self, '_name'):
# expensive calculation
self._name = 1 + 1
return self._name
我是新来的,但我认为缓存可以分解成一个装饰器。只是我没有找到一个这样的;)
PS,真正的计算不依赖于可变值
考虑以下几点:
@property
def name(self):
if not hasattr(self, '_name'):
# expensive calculation
self._name = 1 + 1
return self._name
我是新来的,但我认为缓存可以分解成一个装饰器。只是我没有找到一个这样的;)
PS,真正的计算不依赖于可变值
当前回答
如果你正在使用Django框架,它有这样一个属性来缓存API的视图或响应 使用@cache_page(time),也可以有其他选项。
例子:
@cache_page(60 * 15, cache="special_cache")
def my_view(request):
...
更多细节可以在这里找到。
其他回答
我实现了类似的东西,使用pickle进行持久化,使用sha1进行简短的几乎唯一的id。基本上,缓存对函数代码和参数的历史进行哈希,以获得sha1,然后查找名称为sha1的文件。如果它存在,则打开它并返回结果;如果没有,则调用该函数并保存结果(如果需要一定时间来处理,则可以选择只保存结果)。
也就是说,我发誓我找到了一个现有的模块,它做到了这一点,并发现自己在这里试图找到该模块……我能找到的最接近的是这个,看起来差不多:http://chase-seibert.github.io/blog/2011/11/23/pythondjango-disk-based-caching-decorator.html
我看到的唯一问题是,它不能很好地用于大输入,因为它散列str(arg),这不是唯一的大型数组。
如果有一个unique_hash()协议,让一个类返回其内容的安全散列,那就太好了。我基本上是手动实现我所关心的类型。
听起来好像您不是在要求一个通用的记忆化装饰器(也就是说,您对想要缓存不同参数值的返回值的一般情况不感兴趣)。也就是说,你想要这样:
x = obj.name # expensive
y = obj.name # cheap
而一个通用的记忆装饰器会给你这样的:
x = obj.name() # expensive
y = obj.name() # cheap
我认为方法调用语法是更好的风格,因为它暗示了昂贵计算的可能性,而属性语法暗示了快速查找。
[更新:我之前链接并引用的基于类的记忆化装饰器不适用于方法。我用decorator函数替换了它。如果你愿意使用通用的记忆装饰器,这里有一个简单的:
def memoize(function):
memo = {}
def wrapper(*args):
if args in memo:
return memo[args]
else:
rv = function(*args)
memo[args] = rv
return rv
return wrapper
使用示例:
@memoize
def fibonacci(n):
if n < 2: return n
return fibonacci(n - 1) + fibonacci(n - 2)
可以在这里找到另一个对缓存大小有限制的内存装饰器。
Werkzeug有一个cached_property装饰器(docs, source)
functools。缓存已经在Python 3.9 (docs)中发布:
from functools import cache
@cache
def factorial(n):
return n * factorial(n-1) if n else 1
在以前的Python版本中,早期的答案之一仍然是有效的解决方案:使用lru_cache作为普通缓存,没有限制和lru特性。(文档)
如果maxsize设置为None,将禁用LRU特性,并将缓存 可以不受束缚地成长。
这里有一个更漂亮的版本:
cache = lru_cache(maxsize=None)
@cache
def func(param1):
pass
创建自己的装饰器并使用它
from django.core.cache import cache
import functools
def cache_returned_values(func):
@functools.wraps(func)
def wrapper(*args, **kwargs):
key = "choose a unique key here"
results = cache.get(key)
if not results:
results = func(*args, **kwargs)
cache.set(key, results)
return results
return wrapper
现在看函数
@cache_returned_values
def get_some_values(args):
return x