import threading


def _Memoize(func):
  """Simple thread-safe memoization decorator.

  Uses a repr() of the params. This will be ok unless there is a custom __repr__
  that obscures important information.

  Args:
    func: The function to be memoized.

  Returns:
    A memoized version of func.

  """
  l = threading.Lock()
  cache = {}
  def _Caller(*args, **kwargs):
    with l:
      params = repr((args, kwargs))
      try:
        return cache[params]
      except KeyError:
        result = func(*args, **kwargs)
        cache[params] = result
        return result
  return _Caller