使@lru_cache 忽略一些函数参数
Make @lru_cache ignore some of the function arguments
如何让 @functools.lru_cache
装饰器忽略一些与缓存键有关的函数参数?
例如,我有一个如下所示的函数:
def find_object(db_handle, query):
# (omitted code)
return result
如果我像那样应用 lru_cache
装饰器,db_handle
将包含在缓存键中。因此,如果我尝试使用相同的 query
但不同的 db_handle
调用该函数,它将再次执行,我想避免这种情况。我希望 lru_cache
仅考虑 query
参数。
我至少有一个非常丑陋的解决方案。将 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
用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)))
您将需要安装 cachetools (pip install cachetools
)。
语法是:
@cached(
cache={},
key=lambda <all-function-args>: hashkey(<relevant-args>)
)
这是另一个包含关键字参数的示例:
@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 函数输入参数与 my_func
参数匹配。如果不需要,则不必完全匹配 argspec。例如,您可以使用 kwargs 压缩散列键中不需要的内容:
@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=
参数,因此我们可以使用 ** 将它们全部压缩kwargs.
如何让 @functools.lru_cache
装饰器忽略一些与缓存键有关的函数参数?
例如,我有一个如下所示的函数:
def find_object(db_handle, query):
# (omitted code)
return result
如果我像那样应用 lru_cache
装饰器,db_handle
将包含在缓存键中。因此,如果我尝试使用相同的 query
但不同的 db_handle
调用该函数,它将再次执行,我想避免这种情况。我希望 lru_cache
仅考虑 query
参数。
我至少有一个非常丑陋的解决方案。将 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
用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)))
您将需要安装 cachetools (pip install cachetools
)。
语法是:
@cached(
cache={},
key=lambda <all-function-args>: hashkey(<relevant-args>)
)
这是另一个包含关键字参数的示例:
@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 函数输入参数与 my_func
参数匹配。如果不需要,则不必完全匹配 argspec。例如,您可以使用 kwargs 压缩散列键中不需要的内容:
@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=
参数,因此我们可以使用 ** 将它们全部压缩kwargs.