code: def cached(func):
    
    class Cache(dict):
      def __missing__(self, key):
        result = self[key] = func(*key)
        return result
    cache = Cache()
    f = wraps(func)(lambda *key: cache[key])
    f.cache = cache
    return f
docs: Cache decorator for a function without keyword arguments
  
    You can access the cache contents using the ``cache`` attribute in the
    resulting function, which is a dictionary mapping the arguments tuple to
    the previously returned function result.