缓存特殊调用

Caching for special calls

如何将装饰器 lru_cache 的行为从 functools 更改为使装饰函数具有指示是否缓存此调用的标志。
例如

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

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

我自己做的。

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

考虑这个 - lru_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

如果您要为它编写一个完整的函数,为什么不 copy-paste 原始来源并在那里实现您的逻辑?

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

这样你可以更好地控制函数,你可以很容易地看到所有的东西,你可以用这种方式来玩弄函数工具的内部。