def __call__(self, func):
if self.arg_names is not None:<EOL><INDENT>raise AssertionError("<STR_LIT>")<EOL><DEDENT>self.arg_names = inspect.getfullargspec(func).args<EOL>@wraps(func)<EOL>def wrapper(*args, **kwargs):<EOL><INDENT>key = "<STR_LIT:U+002CU+0020>".join(<EOL>["<STR_LIT>".format(arg_name, arg) for arg_name, arg in<EOL>list(zip(self.arg_names, args)) + [(k, v) for k, v in kwargs.items()]])<EOL>if key not in self.results:<EOL><INDENT>self.calls += <NUM_LIT:1><EOL><DEDENT>self.results[key] = func(*args, **kwargs)<EOL>return self.results[key]<EOL><DEDENT>return wrapper<EOL>
Memoize decorator. Any time a function is called that a memoizer has been attached to its results are stored in
the results dictionary or retrieved from the dictionary if the function has already been called with those
arguments.

Note that the same memoizer persists over all instances of a class. Any state for a given instance that is not
given in the representation of that instance will be ignored. That is, it is possible that the memoizer will
give incorrect results if instance state does not affect __str__ but does affect the value returned by the
memoized method.

Parameters
----------
func: function
    A function for which results should be memoized

Returns
-------
decorated : function
    A function that memoizes results