使@lru_cache忽略一些函数参数

WGH*_*WGH 22 python caching lru functools python-decorators

我怎样才能使@functools.lru_cache装饰器忽略一些关于缓存键的函数参数?

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

def find_object(db_handle, query):
    # (omitted code)
    return result
Run Code Online (Sandbox Code Playgroud)

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

Yan*_*ann 11

使用cachetools,您可以编写:

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)))
Run Code Online (Sandbox Code Playgroud)

  • 您能用什么 key 和 hashkey 详细说明这个答案吗? (8认同)
  • 对于其他想要回答[@Tommy的评论](/sf/ask/2151168841/#comment123792060_32655449)的人来说,我是可以在[cachetools文档的这一部分](https://cachetools.readthedocs.io/en/stable/#cachetools.cached)中找到“key”和“hashkey”的描述。本质上,“key”是一个返回缓存键的函数,“hashkey()”返回其参数的元组作为内部缓存键,并验证每个参数是否可散列。 (5认同)

WGH*_*WGH 9

我至少有一个非常丑陋的解决方案。包装db_handle在一个始终等于的对象中,并在函数内展开它。

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

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
Run Code Online (Sandbox Code Playgroud)