def lru_cache(fn):
@wraps(fn)<EOL>def memoized_fn(*args):<EOL><INDENT>pargs = pickle.dumps(args)<EOL>if pargs not in memoized_fn.cache:<EOL><INDENT>memoized_fn.cache[pargs] = fn(*args)<EOL><DEDENT>return memoized_fn.cache[pargs]<EOL><DEDENT>for attr, value in iter(fn.__dict__.items()):<EOL><INDENT>setattr(memoized_fn, attr, value)<EOL><DEDENT>memoized_fn.cache = {}<EOL>return memoized_fn<EOL>
Memoization wrapper that can handle function attributes, mutable arguments, 
and can be applied either as a decorator or at runtime.

:param fn: Function
:type fn: function
:returns: Memoized function
:rtype: function