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 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
Related Articles
async/await in JavaScript: Making Async Code Readable
Learn how async/await in JavaScript works with clear examples. Understand how it replaces Promise chains, handles errors with try/catch, and makes asynchronous code easier to read.
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.
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.