Open In App

Python Functools – cached_property()

Last Updated : 10 May, 2020
Improve
Improve
Like Article
Like
Save
Share
Report

The @cached_property is a decorator which transforms a method of a class into a property whose value is computed only once and then cached as a normal attribute. Therefore, the cached result will be available as long as the instance will persist and we can use that method as an attribute of a class i.e

Writing    : instance.method
Instead of : instance.method()

cached_property is a part of functools module in Python. It is similar to property(), but cached_property() comes with an extra feature and that is caching.

Note: For more information, refer to Functools module in Python

Why Caching ?

The cache memory is a high-speed memory available inside CPU in order to speed up access to data and instructions. Therefore, the cache is a place that is quick to access. The result can be computed and stored once and from next time, the result can be accessed without recomputing it again. So, it is useful in case of expensive computations.

Difference between @property and @cached_property:




# Using @property
  
# A sample class
class Sample():
  
    def __init__(self):
      self.result = 50
  
    @property
    # a method to increase the value of
    # result by 50
    def increase(self):
        self.result = self.result + 50
        return self.result
  
# obj is an instance of the class sample
obj = Sample()
print(obj.increase)
print(obj.increase)
print(obj.increase)


OUTPUT

100
150
200

Same code but now we use @cached_property instead of @property




# Using @cached_property
  
from functools import cached_property
  
# A sample class
class Sample():
  
    def __init__(self):
      self.result = 50
  
    @cached_property
    # a method to increase the value of
    # result by 50
    def increase(self):
        self.result = self.result + 50
        return self.result
  
# obj is an instance of the class sample
obj = Sample()
print(obj.increase)
print(obj.increase)
print(obj.increase)


OUTPUT

100
100
100

You can clearly see that with @property the value of the result is computed each time the increase() method is called, that’s why it’s valued gets increased by 50. But with @cached_property, the value of the result is computed only once and then stored in the cache, so that it can be accessed each time the increase() method is called without recomputing the value of the result, and that’s why the output shows 100 every time.

But how does it reduces the execution time and makes the program faster ?
Consider the following example:




# Without using @cached_property
  
# A sample class
class Sample():
  
    def __init__(self, lst):
      self.long_list = lst
  
    # a method to find the sum of the 
    # given long list of integer values
    def find_sum(self):
        return (sum(self.long_list))
  
# obj is an instance of the class sample
# the list can be longer, this is just
# an example
obj = Sample([1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
print(obj.find_sum())
print(obj.find_sum())
print(obj.find_sum())


OUTPUT

55
55
55

Here, suppose if we pass a long list of values, the sum of the given list will be computed each time the find_sum() method is called, thereby taking much time for execution, and our program will ultimately become slow. What we want is that, since the list doesn’t change after the creation of the instance, so it would be nice, if the sum of the list is computed only once and not each time when we call the method and wish to access the sum. This can be achieved by using @cached_property

Example:




# With using @cached_property
  
from functools import cached_property
  
# A sample class
class Sample():
    def __init__(self, lst):
      self.long_list = lst
  
    # a method to find the sum of the
    # given long list of integer values
    @cached_property
    def find_sum(self):
        return (sum(self.long_list))
  
# obj is an instance of the class sample
obj = Sample([1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
print(obj.find_sum)
print(obj.find_sum)
print(obj.find_sum)


OUTPUT

55
55
55

Though the output is the same, it reduces the execution time a lot. The sum of the list that is passed at the time of the creation of the instance is computed only once and stored in the cache memory and thereafter, it uses the same, already calculated value of the sum each time we call find_sum() method and saves us form expensive recomputations of the sum. Thus it reduces the execution time and makes our program faster.



Like Article
Suggest improvement
Previous
Next
Share your thoughts in the comments

Similar Reads