如何使用 cachetools ttl_cache 忽略函数参数

How to ignore function arguments with cachetools ttl_cache

我正在利用 cachetools @ttl_cache 装饰器(不是 @cached)。我需要忽略缓存键中的一些参数。例如,.

@ttl_cache(maxsize=1024, ttl=600)
def my_func(foo, ignore_bar, ignore_baz):
    # do stuff

以这种方式工作,我明白了:

>>> my_func("foo", "ignore_bar", "ignore_baz")         # cache miss
>>> my_func("foo", "ignore_bar", "ignore_baz")         # cache hit
>>> my_func("foo", "ignore_bar_bar", "ignore_baz_baz") # cache miss!

我需要的:

>>> my_func("foo", "ignore_bar", "ignore_baz")         # cache miss
>>> my_func("foo", "ignore_bar", "ignore_baz")         # cache hit
>>> my_func("foo", "ignore_bar_bar", "ignore_baz_baz") # cache hit!!!!!

有没有办法使用 @ttl_cache 获得它?

我没有使用过 cachetools,但我出于兴趣查看了文档。显然,没有内置的方法。如果您真的需要此功能,我可以建议您使用如下黑客方法:

class PackedArgs(tuple):
    def __hash__(self):
        return hash(self[0])

    def __eq__(self, other):
        if isinstance(other, self.__class__):
            return self[0] == other[0]
        else:
            return NotImplemented

def pack_args(func):
    def inner(packed_args):
        return func(*packed_args)
    return inner

def unpack_args(func):
    def inner(*args):
        return func(PackedArgs(args))
    return inner

@unpack_args
@ttl_cache(maxsize=1024, ttl=600)
@pack_args
def my_func(foo, ignore_bar, ignore_baz):
    # do stuff

本质上:将您的函数的参数“打包”到一个类似元组的对象,该对象散列为第 0 个元素并导致 @ttl_cache 的行为符合您的需要。然后,“解压”它们以恢复正常界面,并避免在调用时实际必须传递这一大参数。

请注意,这只是一个(非常老套的)概念,我根本没有测试过这段代码。它可能不会像现在这样工作。

顺便说一句,你的要求听起来很有趣。您可以将其作为功能请求提交给 cachetools,并 link 此线程。我可以想象它被实现为类似于 key= kwarg lambda 的东西,类似于内置的 sort

嗯,这正是 @cached 及其自定义 key 参数的用途,所以我想知道您为什么要为此使用 @ttl_cache

from cachetools import TTLCache, cached
from cachetools.keys import hashkey

def mykey(foo, ignore_bar, ignore_baz):
    return hashkey(foo)

@cached(cache=TTLCache(maxsize=1024, ttl=600), key=mykey)
def my_func(foo, ignore_bar, ignore_baz):
    # do stuff