Last active
October 4, 2019 00:00
-
-
Save carlos-jenkins/e13a276edd0a8f8fd59e2aec94619910 to your computer and use it in GitHub Desktop.
Cache the result of a function for certain time.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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