In our previous post What's this in functools? lru_cache, we saw how we can use lru_cache
effectively to speed up execution time of a function that grows exponentially.
Here's three more points to be aware of when using lru_cache
.
The function arguments must be hashable
Since the results are cached using a dictionary, the function arguments must be hashable. This is because the keys of a dictionary must be hashable.
Basically, hashable means that there is a lookup value (i.e. "hash") associated with the object. If something is immutable, and thus can't change, the item can be hashed.
Lists and other mutable objects that can be changed don't have a hash value. More specifically, they don't implement the __hash__ method, but one could be added in a custom class as in this stackoverflow answer.
Therefore, the arguments to the functions you're decorating with lru_cache
should only accept hashable objects.
I.e: Don't use lists or dictionaries as function arguments for functions you decorate with lru_cache
.
Watch out for differing argument patterns
Different argument patterns might get cached differently. For example: f(a=1, b=2)
might get cached differently from f(b=2, a=1)
.
Ok, so, that's easy enough. Just always use the correct order, right?
Well, I sometimes like to do argument unpacking with my parameters using a dict
.
So, instead of f(a=1, b=2)
, I might run:
my_params = {'a': 1, 'b': 2}
f(**my_params)
The problem here is that, depending on what version of Python3 you're using, dictionaries aren't necessarily ordered. If you're using Python 3.7, though, you should be fine.
If you're using a version that doesn't order they keys, then the function could be called sometimes as f(a=1, b=2)
and sometimes f(b=2, a=1)
depending on what gets unpacked first. In these cases you should look into using an OrderedDict
found in the collections
module.
Clearing the cache
You can clear out the cache with the cache_clear()
method.
Comments