Skip to content

Instantly share code, notes, and snippets.

@chris-chris
Forked from adah1972/hashable_cache.py
Created July 22, 2019 06:59
Show Gist options
  • Save chris-chris/c05228a25f1a3a9f296abc80d6019afd to your computer and use it in GitHub Desktop.
Save chris-chris/c05228a25f1a3a9f296abc80d6019afd to your computer and use it in GitHub Desktop.
Decorator for using dicts/lists with any Python cache function (like lru_cache)
# Inspired by https://gist.github.com/harel/9ced5ed51b97a084dec71b9595565a71
from collections import namedtuple
import functools
import json
import six
Serialized = namedtuple('Serialized', 'json')
def hashable_cache(cache):
def hashable_cache_internal(func):
def deserialize(value):
if isinstance(value, Serialized):
return json.loads(value.json)
else:
return value
def func_with_serialized_params(*args, **kwargs):
_args = tuple([deserialize(arg) for arg in args])
_kwargs = {k: deserialize(v) for k, v in six.viewitems(kwargs)}
return func(*_args, **_kwargs)
cached_func = cache(func_with_serialized_params)
@functools.wraps(func)
def hashable_cached_func(*args, **kwargs):
_args = tuple([
Serialized(json.dumps(arg, sort_keys=True))
if type(arg) in (list, dict) else arg
for arg in args
])
_kwargs = {
k: Serialized(json.dumps(v, sort_keys=True))
if type(v) in (list, dict) else v
for k, v in kwargs.items()
}
return cached_func(*_args, **_kwargs)
hashable_cached_func.cache_info = cached_func.cache_info
hashable_cached_func.cache_clear = cached_func.cache_clear
return hashable_cached_func
return hashable_cache_internal
# Example usage below
from cachetools.func import lru_cache
@hashable_cache(lru_cache())
def fib(n):
assert n >= 0
if n == 0:
return 0
elif n == 1:
return 1
else:
return fib(n - 1) + fib(n - 2)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment