I came up with a caching decorator for pure functions. Is it ok? Could it be better/simpler/faster?

def cached(f):    
    def _(*args):
        if args in _._cache:
            return _._cache[args]
            result = f(*args)
            _._cache[args] = result
            return result     
    _._cache = {}
    return _
  • \$\begingroup\$ I mean, not an improvement or anything, but they do have a lru_cache function already built into the library. I would suspect it to be faster than this... In other words, if this is part of a bigger scheme I would consider using lru_cache instead. \$\endgroup\$ – Dair Feb 11 '16 at 9:51
  • \$\begingroup\$ @Dair It might not be available to everyone since lru_cache has only been added in Python 3.2. \$\endgroup\$ – 301_Moved_Permanently Feb 11 '16 at 10:10
  • \$\begingroup\$ @MathiasEttinger: Good point. I still think he should be aware, especially since he hasn't specified his python version. \$\endgroup\$ – Dair Feb 11 '16 at 10:12
  • \$\begingroup\$ @Dair Yes, it's just that, by the look of things, he seems to be using Python 2. But your point remains valid anyway. \$\endgroup\$ – 301_Moved_Permanently Feb 11 '16 at 10:20
  • \$\begingroup\$ I'm using Python 2.6 and LRU cache as I understand it stores only a limited set of latest used results and I need a full cache. \$\endgroup\$ – Eugene Feb 11 '16 at 10:31

What you are trying to achieve is called memoization and has already a number of recipe available on the Python wiki.

Your implementation matches the one using nested functions:

# note that this decorator ignores **kwargs
def memoize(obj):
    cache = obj.cache = {}

    def memoizer(*args, **kwargs):
        if args not in cache:
            cache[args] = obj(*args, **kwargs)
        return cache[args]
    return memoizer

A few things to note here on top of yours:

  • usage of a local variable which resolves faster than an attribute lookup
  • usage of functools.wraps which keeps some properties of the original function intact (name and docstring, mainly)
  • explicit names for variables
  • \$\begingroup\$ What you mean by explicit names for variables? \$\endgroup\$ – Eugene Feb 11 '16 at 10:35
  • \$\begingroup\$ @Eugene _ has no meaning; memoizer has an explicit name which convey meaning. \$\endgroup\$ – 301_Moved_Permanently Feb 11 '16 at 10:37

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.