2

Recently I have seen use of cached_properties decorators in some of the codebases of python 3rd party packages like celery and django (it's also a utility function in Django) and the bottle web framework. There also exists a standalone package for using cached_properties. As far as I understand it's about avoiding heavy computations by providing caching behaviour.

Here is the source code stripped out that implements cached_property:

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."""

    def __init__(self, func):
        self.__doc__ = getattr(func, '__doc__')
        self.func = func

    def __get__(self, obj, cls):
        if obj is None:
            return self
        value = obj.__dict__[self.func.__name__] = self.func(obj)
        return value

and this is how it is used:

class Monopoly(object):

    def __init__(self):
        self.boardwalk_price = 500

    @cached_property
    def boardwalk(self):
        # Again, this is a silly example. Don't worry about it, this is
        #   just an example for clarity.
        self.boardwalk_price += 50
        return self.boardwalk_price

Now when we run it the price stays at $550.

>>> monopoly = Monopoly()
>>> monopoly.boardwalk
550
>>> monopoly.boardwalk
550
>>> monopoly.boardwalk
550

can't we simply store the result of first call to the attribute/property and use it later to avoid recomputation? I am sure this is a very silly question but what am I missing here?

ex:

monopoly = Monopoly()
>>> stored_value = monopoly.boardwalk
550

# now use stored_value instead of making a call to `monopoly.boardwalk`.
2
  • @MartijnPieters thanks a lot i got it :) .but why is question downvoted without a reason? am i missing anything while asking here? Commented Oct 3, 2017 at 7:39
  • Sorry, I can't read minds; voting is anonymous for a reason. The best we can do is point to the tooltip on the downvote button: This question does not show any research effort; it is unclear or not useful; the voter may have felt there was no indication in the question you researched the issue. Again, I can't read minds, or even see who voted. Commented Oct 3, 2017 at 7:45

1 Answer 1

1

Sure you can, but what if there are many different places that use monopoly.boardwalk? Now you have to make sure all those places cache the value locally. Or you could just make the Monopoly class responsible for the caching.

cached_property makes it easy to make the class responsible rather than the consumers of the attribute.

In case you are struggling to find examples of something being used in many different places: in a decently sized Django application you'd have templates, views, and back-end code all potentially touching a given model. Some of those places are in the Django framework itself (like the admin interface), and updating all those places when you add an expensive operation to your model is not practical. Using the decorator is practical; putting the responsibility with the model keeps all that other code simpler.

Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.