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?
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With