def memoize(fun):
 @functools.wraps(fun)
 def wrapper(*args, **kwargs):
  key = (args, frozenset(sorted(kwargs.items())))
  try:
   return cache[key]
  except KeyError:
   ret = cache[key] = fun(*args, **kwargs)
   return ret
 def cache_clear():
  'Clear cache.'
  cache.clear()
 cache = {}
 wrapper.cache_clear = cache_clear
 return wrapper

def memoize ( fun ) : @ functools . wraps ( fun ) def wrapper ( * args , ** kwargs ) : key = ( args , frozenset ( sorted ( kwargs . items ( ) ) ) ) try : return cache [ key ] except KeyError : ret = cache [ key ] = fun ( * args , ** kwargs ) return ret def cache_clear ( ) : cache . clear ( ) cache = { } wrapper . cache_clear = cache_clear return wrapper
decorator to cause a function to cache its results for each combination of inputs and return the cached result on subsequent calls .