code: def memoize(fn):
      
      memoized_values = {}
  
      @wraps(fn)
      def wrapped_fn(*args, **kwargs):
          key = (args, tuple(sorted(kwargs.items())))
          try:
              return memoized_values[key]
          except KeyError:
              memoized_values[key] = fn(*args, **kwargs)
              return memoized_values[key]
  
      return wrapped_fn
docs: Simple memoization decorator for functions and methods,
      assumes that all arguments to the function can be hashed and
      compared.