I want to create a decorator that works like a property, only it calls the decorated function only once, and on subsequent calls always return the result of the first call. An example:
def SomeClass(object):
@LazilyInitializedProperty
def foo(self):
print "Now initializing"
return 5
>>> x = SomeClass()
>>> x.foo
Now initializing
5
>>> x.foo
5
My idea was to write a custom decorator for this. So i started, and this is how far I came:
class LazilyInitializedProperty(object):
def __init__(self, function):
self._function = function
def __set__(self, obj, value):
raise AttributeError("This property is read-only")
def __get__(self, obj, type):
# problem: where to store the value once we have calculated it?
As you can see, I do not know where to store the cached value. The simplest solution seems to be to just maintain a dictionary, but I am wondering if there is a more elegant solution for this.
EDIT Sorry for that, I forgot to mention that I want the property to be read-only.
Denis Otkidach’s CachedAttribute is a method decorator which makes attributes lazy (computed once, accessible many). To make it also read-only, I added a
__set__method. To retain the ability to recalculate (see below) I added a__delete__method:For example:
One of the beautiful things about
CachedAttribute(andReadOnlyCachedAttribute) is that if you
del foo.bar, then the next time youaccess
foo.bar, the value is re-calculated. (This magic is made possible bythe fact that
del foo.barremoves'bar'fromfoo.__dict__but the propertybarremains inFoo.__dict__.)If you don’t need or don’t want this ability to recalculate,
then the following (based on Mike Boers’ lazyprop) is a simpler way to make a read-only lazy property.