Skip to content
5 min read

Python Decorators Explained Without the Confusion

Understand Python decorators clearly with simple examples. Learn what they are, how to write your own, and where they're used in real frameworks like Flask and FastAPI.

#python #intermediate #bestpractices

Python decorators are one of those features that look intimidating at first but click once you see what they actually do. If you’ve used Flask or FastAPI, you’ve already used decorators — @app.route("/") is one. Let’s demystify them.

What Is a Decorator?

A decorator is a function that wraps another function to extend its behaviour without modifying it. In Python, functions are objects — you can pass them as arguments. Decorators exploit this.

def my_decorator(func):
    def wrapper():
        print("Before the function runs")
        func()
        print("After the function runs")
    return wrapper

def say_hello():
    print("Hello!")

# Apply the decorator manually
say_hello = my_decorator(say_hello)
say_hello()

Output:

Before the function runs
Hello!
After the function runs

The @ syntax is just shorthand for this wrapping:

@my_decorator
def say_hello():
    print("Hello!")

Decorators with Arguments

Real-world decorators usually need to handle functions with parameters. Use *args and **kwargs:

import time

def timer(func):
    def wrapper(*args, **kwargs):
        start = time.time()
        result = func(*args, **kwargs)
        end = time.time()
        print(f"{func.__name__} took {end - start:.4f}s")
        return result
    return wrapper

@timer
def slow_function(n):
    return sum(range(n))

slow_function(1_000_000)
# slow_function took 0.0321s

Where You See Decorators in the Wild

  • @app.route("/") — Flask registers the function as a URL handler
  • @app.get("/items") — FastAPI does the same
  • @property — built-in Python, turns a method into an attribute
  • @staticmethod / @classmethod — built-in class decorators
  • @login_required — common in web frameworks for auth checks

Conclusion

Python decorators are just functions that wrap other functions. Once that clicks, reading framework code becomes much clearer. Start by writing a simple logging or timing decorator — it’s the best way to build intuition. Then you’ll read @app.route and know exactly what’s happening under the hood.

Read next: Getting Started with Flask

External resource: Real Python — Primer on Decorators

Kaikobud Sarkar

Kaikobud Sarkar

Software engineer passionate about backend technologies and continuous learning. I write about Python frameworks, cloud architecture, engineering growth, and staying current in tech.

Related Articles

How to Write Clean Functions in JavaScript

Learn how to write clean JavaScript functions that are easy to read, test, and maintain. This guide covers naming, single responsibility, pure functions, and avoiding common pitfalls.

#javascript #bestpractices

CSS Grid vs Flexbox: When to Use Which

Learn when to use CSS Grid vs Flexbox with clear examples. Understand the key differences between one-dimensional and two-dimensional layouts to make the right choice every time.

#css #flexbox