A diary of Andelan #1

(Python cached properties)

Baligh Mehrez
The Andela Way
2 min readDec 13, 2019

--

Photo by Hitesh Choudhary on Unsplash

In this series, I will talk about the daily challenges we face at our work as Andelans (Andela’s Software Engineers) and how we overcome them.

Yesterday I was asked by my teammate (Why we use the @cached_property decorator and not easily use the most common one @property ?).

To illustrate the idea behind @cached_property let’s begin with what the @propery decorator does in our classes.

Consider this code:

A code sample demonstrates Python properties

In the above example, the “@property” decorator turns our class method “color” to a class property, so it is easy for us to assign values to or read from.

The idea here is that we need to do some coding before assigning a value to our property or even before reading it.

Each time we assign a value to our object property like

cat_object.color = "black"

the class method “color( self, c)” will be executed.

And each time we read this value

cat_color = cat_object.color

the class method “color(self)” will be executed.

Now consider the following code:

A code sample demonstrates slow Python properties

And here is the output:

2019-12-07 12:42:51.352631
Getting the value of the color property
gray
2019-12-07 12:42:56.367541
Getting the value of the color property
gray
2019-12-07 12:43:01.367779
Process finished with exit code 0

From the output, it is clear that each time we call our property the code will be executed and it costs us 5 seconds.

What if we don’t need this costly process to run each time?!

It is clear that after we query our DB and get the value nothing will change.

let’s do the magic. The “@cached_propery” decorator.

Beginning with Python 3.8 “@cached_property” became a part of Python standard library “functools.py” and is defined from “https://docs.python.org/3/library/functools.html” as follows:

@functools.cached_property(func)Transform a method of a class into a property whose value is computed once and then cached as a normal attribute for the life of the instance. Similar to property(), with the addition of caching. Useful for expensive computed properties of instances that are otherwise effectively immutable.

For earlier versions of Python, you can import “cached_property” from “werkzeug.utils”.

Let’s see an example:

And the output:

2019-12-07 13:02:12.895058
Getting the value of the color property
gray
2019-12-07 13:02:17.896651
gray
2019-12-07 13:02:17.896840
Process finished with exit code 0

As you can see from the second call of the property there is no execution of the method, no printing for “Getting the value of the color property”, and no waiting.

Conclusion:-

Properties caching in Python could give you great performance improvements and save you a lot of time running the same slow code again and again.

--

--