首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >让@lru_cache忽略一些函数参数

让@lru_cache忽略一些函数参数
EN

Stack Overflow用户
提问于 2015-06-09 11:41:10
回答 2查看 13K关注 0票数 69

如何使@functools.lru_cache装饰器忽略与缓存键有关的一些函数参数?

例如,我有一个如下所示的函数:

代码语言:javascript
复制
def find_object(db_handle, query):
    # (omitted code)
    return result

如果我像这样应用lru_cache装饰器,db_handle将包括在缓存键中。因此,如果我尝试用相同的query,但不同的db_handle调用函数,它将再次被执行,这是我想要避免的。我希望lru_cache只考虑query参数。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2015-09-18 15:13:10

使用缓存工具,您可以编写:

代码语言:javascript
复制
from cachetools import cached
from cachetools.keys import hashkey

from random import randint

@cached(cache={}, key=lambda db_handle, query: hashkey(query))
def find_object(db_handle, query):
    print("processing {0}".format(query))
    return query

queries = list(range(5))
queries.extend(range(5))
for q in queries:
    print("result: {0}".format(find_object(randint(0, 1000), q)))

您需要安装cachetools (pip install cachetools)。

语法是:

代码语言:javascript
复制
@cached(
    cache={},
    key=lambda <all-function-args>: hashkey(<relevant-args>)
)

下面是另一个包含关键字args的示例:

代码语言:javascript
复制
@cached(
    cache={},
    key=lambda a, b, c=1, d=2: hashkey(a, c)
)
def my_func(a, b, c=1, d=2):
    return a + c

在上面的示例中,请注意lambda函数输入args与my_func args匹配。如果你不需要的话,你不需要完全匹配argspec。例如,您可以使用kwargs来压缩hashkey中不需要的内容:

代码语言:javascript
复制
@cached(
    cache={},
    key=lambda a, b, c=1, **kwargs: hashkey(a, c)
)
def my_func(a, b, c=1, d=2, e=3, f=4):
    return a + c

在上面的示例中,我们在查找缓存值时并不关心d=e=f= args,因此我们可以使用**kwargs将它们全部压缩。

票数 61
EN

Stack Overflow用户

发布于 2015-06-09 16:53:48

我至少有一个很难看的解决方案。将db_handle包装在一个总是相等的对象中,并在函数中展开它。

它需要一个带有相当多的辅助函数的装饰器,这使得堆栈跟踪非常混乱。

代码语言:javascript
复制
class _Equals(object):
    def __init__(self, o):
        self.obj = o

    def __eq__(self, other):
        return True

    def __hash__(self):
        return 0

def lru_cache_ignoring_first_argument(*args, **kwargs):
    lru_decorator = functools.lru_cache(*args, **kwargs)

    def decorator(f):
        @lru_decorator
        def helper(arg1, *args, **kwargs):
            arg1 = arg1.obj
            return f(arg1, *args, **kwargs)

        @functools.wraps(f)
        def function(arg1, *args, **kwargs):
            arg1 = _Equals(arg1)
            return helper(arg1, *args, **kwargs)

        return function

    return decorator
票数 13
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/30730983

复制
相关文章

相似问题

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