def get_important_data(self):
if not hasattr(self, _important_data):
self._important_data = self.get_result_of_lots_of_queries()
return self._important_data
If you call this function once on an object, it will run a lot of queries, but will store the result in self._important_data. The next time you call the function on this exact same object, the attribute self._important_data will still be set and the huge load of queries do not have to be executed again.In some projects you have to create such a function more than once, for whatever reason. A colleague got sick and tired of writing the same code over and over again and came up with an idea to tackle this concurrency. So he asked me if, when I had little to do, I could write a decorator that does exactly the same kind of 'caching' as the function above. I however have little to no experience in writing decorators, so I copy/pasted something together from the interwebz, that seems to do what I want.
This is what I came up with.
in decorators.py:
from functools import wraps
def cached_function(attr):
def inner_cached_function(fn):
def return_attr(*args, **kwargs):
try:
cls = args[0].__class__ # args[0] should be fn's self
except:
raise Exception("""A function with the cached_function
decorator must use 'self' as first argument""")
if not hasattr(cls, attr):
value = fn(*args, **kwargs)
setattr(cls, attr, value)
return getattr(cls, attr)
return wraps(fn)(return_attr)
return inner_cached_function
in a ModelClass:
@cached_function('_important_data')
def get_important_data(self):
return self.get_result_of_lots_of_queries()
As said/written before, I almost have no experience with this, so please comment if you have anything to say about this solution.Thanks :-)