Calculation =========== .. decorator:: memoize(*, key_func=None) Memoizes decorated function results, trading memory for performance. Can skip memoization for failed calculation attempts:: @memoize # Omitting parentheses is ok def ip_to_city(ip): try: return request_city_from_slow_service(ip) except NotFound: return None # return None and memoize it except Timeout: raise memoize.skip(CITY) # return CITY, but don't memoize it Additionally ``@memoize`` exposes its memory for you to manipulate:: # Prefill memory ip_to_city.memory.update({...}) # Forget everything ip_to_city.memory.clear() Custom `key_func` could be used to work with unhashable objects, insignificant arguments, etc:: @memoize(key_func=lambda obj, verbose=None: obj.key) def do_things(obj, verbose=False): # ... .. decorator:: make_lookuper As :func:`@memoize`, but with prefilled memory. Decorated function should return all available arg-value pairs, which should be a dict or a sequence of pairs. Resulting function will raise ``LookupError`` for any argument missing in it:: @make_lookuper def city_location(): return {row['city']: row['location'] for row in fetch_city_locations()} If decorated function has arguments then separate lookuper with its own lookup table is created for each combination of arguments. This can be used to make lookup tables on demand:: @make_lookuper def function_lookup(f): return {x: f(x) for x in range(100)} fast_sin = function_lookup(math.sin) fast_cos = function_lookup(math.cos) Or load some resources, memoize them and use as a function:: @make_lookuper def translate(lang): return make_list_of_pairs(load_translation_file(lang)) russian_phrases = lmap(translate('ru'), english_phrases) .. decorator:: silent_lookuper Same as :func:`@make_lookuper`, but returns ``None`` on memory miss. .. decorator:: cache(timeout, *, key_func=None) Caches decorated function results for ``timeout``. It can be either number of seconds or :class:`py3:datetime.timedelta`:: @cache(60 * 60) def api_call(query): # ... Cache can be invalidated before timeout with:: api_call.invalidate(query) # Forget cache for query api_call.invalidate_all() # Forget everything Custom ``key_func`` could be used same way as in :func:`@memoize`:: # Do not use token in cache key @cache(60 * 60, key_func=lambda query, token=None: query) def api_call(query, token=None): # ... .. raw:: html :file: descriptions.html