首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >选择性缓存/回忆录的装饰器

选择性缓存/回忆录的装饰器
EN

Stack Overflow用户
提问于 2015-02-04 00:01:58
回答 4查看 896关注 0票数 4

我正在寻找一种构建装饰器@memoize的方法,我可以在下面的函数中使用该方法:

代码语言:javascript
复制
@memoize
my_function(a, b, c):
    # Do stuff 
    # result may not always be the same for fixed (a,b,c)
return result

那么,如果我做了:

代码语言:javascript
复制
result1 = my_function(a=1,b=2,c=3)
# The function f runs (slow). We cache the result for later

result2 = my_function(a=1, b=2, c=3)
# The decorator reads the cache and returns the result (fast)

现在假设我希望强制缓存更新

代码语言:javascript
复制
result3 = my_function(a=1, b=2, c=3, force_update=True)
# The function runs *again* for values a, b, and c. 

result4 = my_function(a=1, b=2, c=3)
# We read the cache

在上面的末尾,我们总是有result4 = result3,但不一定是result4 = result,这就是为什么需要一个选项来强制对相同的输入参数进行缓存更新。

我如何处理这个问题?

关于joblib的注记

据我所知,joblib支持强制重新运行的.call,但它支持不更新缓存。

跟踪使用klepto的情况

是否有任何方法让klepto (请参阅@Wally的答案)默认情况下在特定位置缓存其结果?(例如/some/path/)并跨多个函数共享这个位置?我想说

代码语言:javascript
复制
cache_path = "/some/path/"

然后在同一路径下对给定模块中的几个函数进行@memoize

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2015-02-04 00:16:42

我建议看看joblibklepto。两者都有非常可配置的缓存算法,并且可以做您想做的事情。

两者都可以为result1result2进行缓存,klepto提供对缓存的访问,因此可以从本地内存缓存(而不是从存储的存档中删除结果,例如在数据库中)获得结果。

代码语言:javascript
复制
>>> import klepto
>>> from klepto import lru_cache as memoize
>>> from klepto.keymaps import hashmap
>>> hasher = hashmap(algorithm='md5')
>>> @memoize(keymap=hasher)
... def squared(x):
...   print("called")
...   return x**2
... 
>>> squared(1)
called
1
>>> squared(2)
called
4
>>> squared(3)
called
9
>>> squared(2)
4
>>> 
>>> cache = squared.__cache__()
>>> # delete the 'key' for x=2
>>> cache.pop(squared.key(2))
4
>>> squared(2)
called
4

不完全是你想要的关键字界面,但它有你想要的功能。

票数 4
EN

Stack Overflow用户

发布于 2015-02-04 00:25:27

你可以这样做:

代码语言:javascript
复制
import cPickle


def memoize(func):
    cache = {}

    def decorator(*args, **kwargs):
        force_update = kwargs.pop('force_update', None)
        key = cPickle.dumps((args, kwargs))
        if force_update or key not in cache:
            res = func(*args, **kwargs)
            cache[key] = res
        else:
            res = cache[key]
        return res
    return decorator

修饰器接受额外的参数force_update (您不需要在函数中声明它)。它从kwargs弹出。所以没有用这些参数调用函数,或者传递给force_update = True,函数将被调用:

代码语言:javascript
复制
@memoize
def f(a=0, b=0, c=0):
    import random
    return [a, b, c, random.randint(1, 10)]


>>> print f(a=1, b=2, c=3)
[1, 2, 3, 9]
>>> print f(a=1, b=2, c=3) # value will be taken from the cache
[1, 2, 3, 9]
>>> print f(a=1, b=2, c=3, force_update=True)
[1, 2, 3, 2]
>>> print f(a=1, b=2, c=3) # value will be taken from the cache as well
[1, 2, 3, 2]
票数 2
EN

Stack Overflow用户

发布于 2015-02-04 00:28:03

如果你想自己做:

代码语言:javascript
复制
def memoize(func):
    cache = {}
    def cacher(a, b, c, force_update=False):
        if force_update or (a, b, c) not in cache:
            cache[(a, b, c)] = func(a, b, c)
        return cache[(a, b, c)]
    return cacher
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/28311141

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档