Skip to content

Instantly share code, notes, and snippets.

@carlos-jenkins
Last active October 4, 2019 00:00
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save carlos-jenkins/e13a276edd0a8f8fd59e2aec94619910 to your computer and use it in GitHub Desktop.
Save carlos-jenkins/e13a276edd0a8f8fd59e2aec94619910 to your computer and use it in GitHub Desktop.
Cache the result of a function for certain time.
from time import monotonic
from functools import wraps
def cache(expiration_s):
"""
Cache the result of a function for certain time.
There is one restriction: all arguments of the wrapped function must be
immutable, that is, they must be used as key in a dictionary.
Usage::
from time import time
@cache(10.0)
def foo(ham, jam):
return time()
The above will cache the value returned by the function for 10 seconds for
specific values for `ham` and `jam`.
:param float expiration_s: Time in second for how long the cache is valid.
:return: a decorator.
:rtype: function
"""
cache = {}
def decorator(function):
@wraps(function)
def replacement(*args, **kwargs):
# Determine unique signature for the call
signature = tuple(args) + tuple(sorted(
((name, value) for name, value in kwargs.items()),
key=lambda e: e[0],
))
# Fetch the cache and check if still valid
when, cached = cache.get(signature, (None, None))
now = monotonic()
if when is not None and (now - when) < expiration_s:
return cached
# Call function and save the result into the cache
new = function(*args, **kwargs)
cache[signature] = (now, new)
return new
return replacement
return decorator
__all__ = [
'cache',
]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment