utils.functional.cached_property

class cached_property(object, name) [source]

The @cached_property decorator caches the result of a method with a single self argument as a property. The cached result will persist as long as the instance does, so if the instance is passed around and the function subsequently invoked, the cached result will be returned.

Consider a typical case, where a view might need to call a model’s method to perform some computation, before placing the model instance into the context, where the template might invoke the method once more:

# the model
class Person(models.Model):

    def friends(self):
        # expensive computation
        ...
        return friends

# in the view:
if person.friends():
    ...

And in the template you would have:

{% for friend in person.friends %}

Here, friends() will be called twice. Since the instance person in the view and the template are the same, @cached_property can avoid that:

from django.utils.functional import cached_property

@cached_property
def friends(self):
    # expensive computation
    ...
    return friends

Note that as the method is now a property, in Python code it will need to be invoked appropriately:

# in the view:
if person.friends:
    ...

The cached value can be treated like an ordinary attribute of the instance:

# clear it, requiring re-computation next time it's called
del person.friends # or delattr(person, "friends")

# set a value manually, that will persist on the instance until cleared
person.friends = ["Huckleberry Finn", "Tom Sawyer"]

As well as offering potential performance advantages, @cached_property can ensure that an attribute’s value does not change unexpectedly over the life of an instance. This could occur with a method whose computation is based on datetime.now(), or simply if a change were saved to the database by some other process in the brief interval between subsequent invocations of a method on the same instance.

You can use the name argument to make cached properties of other methods. For example, if you had an expensive get_friends() method and wanted to allow calling it without retrieving the cached value, you could write:

friends = cached_property(get_friends, name='friends')

While person.get_friends() will recompute the friends on each call, the value of the cached property will persist until you delete it as described above:

x = person.friends         # calls first time
y = person.get_friends()   # calls again
z = person.friends         # does not call
x is z                     # is True
doc_Django
2016-10-09 18:40:29
Comments
Leave a Comment

Please login to continue.