Reputation: 1519
In my scenario, I have a class with many properties. The properties don't take any parameters, they are heavy in calculation time, and their results should not change during the program lifecycle.
I want to cache the results of those properties, so the heavy calculation is done only once. The approach that I took is with decorators:
def cached(f):
def wrapper(*args):
# get self
class_self = args[0]
cache_attr_name = '_' + f.__name__
if hasattr(class_self, cache_attr_name):
return getattr(class_self, cache_attr_name)
else:
result = f(*args)
setattr(class_self, cache_attr_name, result)
return result
return wrapper
and then in the cached class members:
class MyClass():
@property
@cached
def heavy_prop(self):
# In the actual class, the heavy calculation happens here
return 1
Any ideas for a better/other solution for this case?
Upvotes: 0
Views: 2105
Reputation: 36033
For Python 3.8, use the built in cached_property
: https://docs.python.org/dev/library/functools.html#functools.cached_property
For older versions, use the library https://github.com/pydanny/cached-property
Or just use this code:
class cached_property(object):
"""
A property that is only computed once per instance and then replaces itself
with an ordinary attribute. Deleting the attribute resets the property.
Based on https://github.com/pydanny/cached-property/blob/master/cached_property.py
"""
def __init__(self, func):
self.__doc__ = func.__doc__
self.func = func
def cached_property_wrapper(self, obj, _cls):
if obj is None:
return self
value = obj.__dict__[self.func.__name__] = self.func(obj)
return value
__get__ = cached_property_wrapper
Upvotes: 3