top of page

Decorators: Caching and Timing via Decorators

  • Writer: Mic
    Mic
  • Nov 25, 2025
  • 3 min read

While teaching maths at university, it’s pretty common for my students to suddenly find themselves doing a bit of coding. When that happens, Python is usually the language of choice—it’s friendly, forgiving, and doesn’t ask too many questions.

Letting generative AI run with the prompt: Interpret python and decorator

One idea that tends to make newcomers pause, squint at the screen, and reread the same line three times is decorators (yes, that weird @ thing in front of some functions). This post is the first in a small series where we’ll unpack different useful decorators, what they actually do, and why they’re less scary—and more helpful—than they first appear.


The Basic example: Timing

Just about everyone who has ever looked at a tutorial for Python has come across the classic example of a timing decorator.

This example does a great job of showing how to write a decorator and what it does. What it doesn’t do so well is help with practical, beginner-level problems. Let’s be honest: when you’re just starting out with Python, worrying about how fast your function runs usually isn’t top of the list. And if performance is the thing you’re most excited about right away… well, that’s awesome too — it might just mean languages like C or Rust are waiting for you down the road 😉


More useful: Caching

Another simple example that’s far more useful is caching—especially for students who end up doing the same calculations over and over again for their work. One of the most classic cases of repetitive computation is calculating Fibonacci numbers. It’s a simple starting exercise for just about anyone using Python for numerical or computational work.

Even a small experiment without caching quickly shows just how useful this decorator can be. For a number as modest as 40, you can already see a difference of several seconds in a simple calculation like this.

Along the same lines, you could apply the very same decorator to something like a straightforward prime factorisation function—especially if you find yourself needing those results repeatedly.

If we combine this with the time_my_function decorator, we can immediately compare the two approaches and see the difference in action. Even on a fairly ordinary laptop, the uncached version took about 3.1 seconds, while the cached version finished in roughly 0.38 seconds—a pretty convincing win for a single line of decoration (your mileage may vary, of course).


Caching: but not forever

If our cache isn’t storing the result of a pure calculation, but something pulled from the real world—an API call, a database query, or any other regularly updated source—then caching “forever” can get… awkward. In those cases, we usually want the cache to come with an expiry date, so it stays valid only for a certain amount of time before it refreshes.

In this case, the second API call is still considered “recent enough,” so we don’t ask again and simply reuse the cached result. By the third call, the data is old enough to trigger an update, and the fourth call once again pulls from the cache. This kind of setup is especially handy when you’re running a simulation that depends on data from an external API, but you don’t want that data to refresh constantly while the simulation is running.


Last little note

These two decorators are simple, but already genuinely useful for beginners. The first one is great for clearly showing what a decorator is and how it works. The second is practical from day one—especially for anyone starting to use Python to tackle more calculation-heavy problems.



Comments


bottom of page