I was generating some reports recently that involved accessing expensive object methods whose results were known to not change on subsequent calls; However, instead of using local variables, I sketched-out this quick memoization decorator to save method responses as variables on the object (using a leading '_' followed by the method-name as the variable name):
def cache_method_results(fn):
def _view(self, *args, **kwargs):
var_name = '_{n}'.format(n=fn.__name__)
if var_name in self.__dict__: # Return the copy we have
return self.__dict__[var_name]
else: # Run the function and save its result
self.__dict__[var_name] = fn(self, *args, **kwargs)
return self.__dict__[var_name]
return _view
You might use it like this:
class Foo(object):
@cache_method_results
def some_expensive_operation(self):
...calculate something big and unchanging...
return results
f = Foo()
print(f.some_expensive_operation()) # This first call will run the calculation
...
print(f.some_expensive_operation()) # but this one will used the cached result instead
It's not rocket science, but these little tricks add to the fun of using Python.