While looking through the webapp2 documentation online, I found information on the decoratorwebapp2.cached_property
(which can be found at https://webapp-improved.appspot.com/api/webapp2.html#webapp2.cached_property).
In the documentation, it says:
A decorator that converts a function into a lazy property.
My question is:
- What is a lazy property?
Thanks!
It is a
property
decorator that gets out of the way after the first call. It allows you to auto-cache a computed value.The standard library
@property
decorator is a data descriptor object and is always called, even if there is an attribute on the instance of the same name.The
@cached_property
decorator on the other hand, only has a__get__
method, which means that it is not called if there is an attribute with the same name already present. It makes use of this by setting an attribute with the same name on the instance on the first call.Given a
@cached_property
-decoratedbar
method on an instance namedfoo
, this is what happens:Python resolves
foo.bar
. Nobar
attribute is found on the instance.Python finds the
bar
descriptor on the class, and calls__get__
on that.The
cached_property
__get__
method calls the decoratedbar
method.The
bar
method calculates something, and returns the string'spam'
.The
cached_property
__get__
method takes the return value and sets a new attributebar
on the instance;foo.bar = 'spam'
.The
cached_property
__get__
method returns the'spam'
return value.If you ask for
foo.bar
again, Python finds thebar
attribute on the instance, and uses that from here on out.Also see the source code for the original Werkzeug implementation:
Note that as of Python 3.8, the standard library has a similar object,
@functools.cached_property()
. It's implementation is a little bit more robust, it guards against accidental re-use under a different name, produces a better error message if used on an object without a__dict__
attribute or where that object doesn't support item assignment, and is also thread-safe.