On 2 December 2014 at 08:41, Cameron Simpson email@example.com wrote:
On 01Dec2014 17:34, Constantin Berhard firstname.lastname@example.org wrote:
One strength of the functools.lru_cache lies in caching results of calls initiated by the function itself (i.e. recursive call results).
However because of the exception, the intermediate results from the tail recursion don't end up in the cache, if my tail call optimization is used together with lru_cache.
So I would like to be able to manually add argument-result pairs in the cache. A manual lookup is not needed for my purpose, but I propose that there should be methods to
- add argument-result pairs to the cache
- lookup if there is a result for given arguments
- lookup the result for given arguments if it exists (exception thrown
otherwise) 4. invalidate specific cache entries (at the moment you can only invalidate the cache as a whole through func.cache_clear())
What do you think?
I'm kind of +1 on this, but I'd be for a different exposure. Let lru_cache expose a mapping of the cache. Once you have that mapping, expecially if it is just a dict, everything else comes for free.
In fact, I'd advocate moving the LRU cache supporting object off into collections and building functools.lru_cache on top of that. Use case: I had to write my own LRU cache bcause I wasn't just wrapping a function. Having that available as a standalone object from collections which looked like a lossy mapping (i.e. things vanish from the mapping when the cache overflows) would be immensely useful.
As far as I'm aware, this is actually a deliberate design decision. There are so many degrees of freedom in designing a cache API that without constrainting the usage model it's really quite difficult to come up with a flexible abstraction that's easier to use than just building your own custom caching class.
And once you expose the underlying mapping in functools.lru_cache itself, it hugely constraints the internal implementation of that cache (since you just made a whole lot of things that are currently implementation details part of the public API).
So collections.OrderedDict provides the raw building block needed to implement an LRU cache, while functools.lru_cache applies that building block to a particular use case.
It's OK if folks with needs that don't quite fit the standard idiom write their own custom class to handle it - that makes it possible to keep the standard tools simple to handle the standard cases, while folks with different needs can just write something specifically tailored to their situation, rather than trying to learn and configure a more generic API.