Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does my LRU cache miss with the same argument?

I have some code that looks like this:

from functools import lru_cache


@lru_cache()
def get_cheese(type):
    print('{}? We\'re all out.'.format(type))
    return None

get_cheese(type='cheddar')
get_cheese('cheddar')
print(get_cheese.cache_info())

cache_info() reports that there were two misses - yet I called the function with the same argument.

It actually took some doing, but I figured out that it's because in one instance I was using the keyword arg, and the other I was using a positional argument.

But why?

like image 750
Wayne Werner Avatar asked Mar 01 '16 20:03

Wayne Werner


1 Answers

The wrapper created by functools.lru_cache makes no attempt to inspect or copy the signature of the wrapped function. The Python version is defined as

def wrapper(*args, **kwargs):
    ...
    key = make_key(args, kwds, typed)
    ...

and as you can see, it builds the key used in the cache based on args and kwargs, without knowing whether any positional or keyword arguments are equivalent. The C version similarly builds the key without caring about the original signature.

As for why it's designed that way? I'm not aware of the original rationale. It could have been deliberate, either for simplicity of implementation or to avoid the overhead of matching keyword arguments to positionals, or it could have been an oversight. If you think changing it would be worthwhile, you could bring it up on the issue tracker.

like image 196
user2357112 supports Monica Avatar answered Sep 27 '22 17:09

user2357112 supports Monica