In Python, decorators let you add new features to a function without changing its code. It's like adding an extra layer of behavior before or after a function runs.
Let’s understand decorators with real-life example.
🧼Wearing socks before shoes
Imagine every time you put on shoes, you always wear socks first. Instead of reminding yourself each time, you could set a rule: "Before wearing shoes, wear socks automatically."
In Python, decorators let you set such rules for functions: "Before or after this function runs, do something extra."
🔰 A simple example
Output
Putting on socks...
Shoes are on!
Now wearing shoes.
Explanation
add_behavior is the decorator.
It wraps wear_shoes with extra code before and after.
@add_behavior is just a shortcut for: wear_shoes = add_behavior(wear_shoes)
🧩 What is wrapper?
wrapper is the inner function inside a decorator.
It wraps the original function so you can run extra code before or after it.
def my_decorator(func):
def wrapper():
print("Before")
func()
print("After")
return wrapper
🔖 What does @ do?
The @ symbol is just Python shorthand. These two lines are equivalent:
@my_decorator
def say_hello():
print("Hello")
def say_hello():
print("Hello")
say_hello = my_decorator(say_hello)
📌 Why put @decorator right before the function?
Because this is the function you're modifying. Putting @decorator right above it tells Python: “Wrap this function with the decorator right now.”
It keeps your code clean and easy to understand.
➕ Can I use the same decorator on multiple functions?
Yes! That's the main advantage of decorators—they're reusable.
Output
Running: task_one
Doing task one.
Running: task_two
Doing task two.
🤝 Decorator that accepts arguments
Sometimes, you want your decorator to take its own input, like how many times to repeat something. This is different from a normal decorator, which just wraps a function without any extra settings.
Here is an example that show how decorators can accept arguments:
🔁 Repeat a Message
Output
Hello!
Hello!
Hello!
Explanation
repeat(3) creates a custom decorator that repeats the function 3 times.
@repeat(3) is the same as doing say_hello = repeat(3)(say_hello).
It works by first calling repeat(3) which returns a decorator, and that decorator wraps the function.
💼 Use cases
💡 You may think decorators run immediately — but they don’t.
They wrap the original function and return a new one.
The wrapped logic only runs when the function is called — not when it's defined.
However, they're widely used in real-world codebases.
Here are a few practical use cases:
Yes, if you find yourself repeating setup or cleanup tasks around multiple functions, decorators let you extract that into reusable logic.
🛒 In Shopping App: Confirming Purchase
🧑🍳 In Kitchen App: Clean Before Cooking
📆 Let's start using it
Decorators let you "wrap" extra behavior around your functions.
They're useful in real-world tasks like logging, access control, and timing.
You can use function, method, and class decorators depending on what you need.
Start with small examples. Once you're comfortable, you can apply decorators in real projects across any domain.
Happy coding! 🚀