Caching for special calls

118 views Asked by At

How can you change the behavior of the decorator lru_cache from functools so that the decorated function has a flag that indicates whether to cache this call or not.
for example

@new_lru_cache
def f(args, kwargs):
    ...body function...

f(1) # not saved
f(2, cache=True) # saved
3

There are 3 answers

0
Işık Kaplan On BEST ANSWER

If you are gonna write a whole function for it, why not copy-paste the original source and implement your logic there?

def lru_cache(maxsize=128, typed=False, cache=False):
    if isinstance(maxsize, int):
        if maxsize < 0:
            maxsize = 0
    elif callable(maxsize) and isinstance(typed, bool):
        user_function, maxsize = maxsize, 128
        wrapper = _lru_cache_wrapper(user_function, maxsize, typed, _CacheInfo)
        return update_wrapper(wrapper, user_function)
    elif maxsize is not None:
        raise TypeError('Expected first argument to be an integer, a callable, or None')

    def decorating_function(user_function):
        if not cache:
            return user_function # We add here
        wrapper = _lru_cache_wrapper(user_function, maxsize, typed, _CacheInfo)
        return update_wrapper(wrapper, user_function)

    return decorating_function

This way you have even more control over the function, and you can see everything easily, and you can play around with the inners of the functools this way.

0
Владислав Харламов On

I did it myself.

def new_lru_cache(f):
    g = None
    def inner(*args, cache=False, **kwargs):
        if cache:
            nonlocal g
            if g is None:
                g = lru_cache(f)
            return g(*args, **kwargs)
        else:
            return f(*args, **kwargs)
    return inner
0
hexbioc On

Consider this - an extension of lru_cache, allowing access to configure the cache.

from functools import lru_cache

def controlled_lru_cache(*lru_args, **lru_kwargs):
    def decorator(func):
        func_with_cache = lru_cache(*lru_args, **lru_kwargs)(func)
        def decorated(*args, cache=False, **kwargs):
            if cache:
                return func_with_cache(*args, **kwargs) 
            return func(*args, **kwargs)
        return decorated
    return decorator

@controlled_lru_cache(maxsize=64)
def square(n):
    return n * n