pythoncachingpython-decoratorslrufunctools

Make @lru_cache ignore some of the function arguments


How can I make @functools.lru_cache decorator ignore some of the function arguments with regard to caching key?

For example, I have a function that looks like this:

def find_object(db_handle, query):
    # (omitted code)
    return result

If I apply lru_cache decorator just like that, db_handle will be included in the cache key. As a result, if I try to call the function with the same query, but different db_handle, it will be executed again, which I'd like to avoid. I want lru_cache to consider query argument only.


Solution

  • With cachetools you can write:

    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)))
    

    You will need to install cachetools (pip install cachetools).

    The syntax is:

    @cached(
        cache={},
        key=lambda <all-function-args>: hashkey(<relevant-args>)
    )
    

    Here is another example that includes keyword 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
    

    In the example above note that the lambda function input args match the my_func args. You don't have to exactly match the argspec if you don't need to. For example, you can use kwargs to squash out things that aren't needed in the hashkey:

    @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
    

    In the above example we don't care about d=, e= and f= args when looking up a cache value, so we can squash them all out with **kwargs.