Python Decorator Example (Simple Use Case)
If you are new to decorators, the easiest way to understand them is to see one small example that works.
This page shows a simple decorator that wraps a function, runs code before and after it, and helps you see why decorators are useful. It does not try to cover every decorator pattern.
Page goal
This example focuses on one clear idea:
- Understand a simple decorator by example
- Read the code step by step
- Run it yourself and see the output
If you want the full beginner explanation later, see Decorators in Python: beginner introduction.
A simple runnable decorator example
def show_before_after(func):
def wrapper():
print("Before function runs")
func()
print("After function runs")
return wrapper
@show_before_after
def say_hello():
print("Hello!")
say_hello()
This is the main pattern to notice:
show_before_aftertakes a function as input- It defines a new function called
wrapper wrapperruns extra codewrapperalso calls the original function- The decorator returns
wrapper
What the example shows
This one example teaches the basic decorator idea:
- A decorator takes a function
- It returns a new function
- The new function runs extra code before and after the original function
- The
@decorator_namesyntax is a shortcut
If you already understand what a function is in Python, this pattern will make more sense.
How to read the code step by step
1. Define the decorator
def show_before_after(func):
This creates a decorator function.
The parameter func is the function being decorated.
2. Define wrapper() inside the decorator
def wrapper():
This inner function is the new function that will replace the original one.
3. Run code before the original function
print("Before function runs")
This is extra behavior added by the decorator.
4. Call the original function
func()
This runs the original function that was passed into the decorator.
Be careful here:
funcmeans the function itselffunc()means “run the function”
5. Run code after the original function
print("After function runs")
This is another piece of added behavior.
6. Return wrapper
return wrapper
This is a very important line.
It means the decorator gives back the new wrapped function.
If you forget this line, the decorator will not work correctly.
7. Apply the decorator with @show_before_after
@show_before_after
def say_hello():
print("Hello!")
This is a shorter way to write:
def say_hello():
print("Hello!")
say_hello = show_before_after(say_hello)
Both versions do the same thing.
8. Call the decorated function normally
say_hello()
Even though say_hello was decorated, you still call it like a normal function.
If you need a refresher, see Python functions explained or how to create a simple function in Python.
Expected output
When you run the code, you should see:
Before function runs
Hello!
After function runs
That output shows the order clearly:
- The decorator runs code before
- The original function runs
- The decorator runs code after
Why beginners use decorators
Beginners usually meet decorators when they want to add repeated behavior without rewriting the same code again and again.
A decorator can help you:
- Add messages before or after a function runs
- Log information
- Time how long a function takes
- Check permissions or access
- Reuse the same pattern across many functions
The big benefit is this:
- You do not need to change the original function body each time
- You avoid copying the same extra code into many functions
Important limitation of this simple example
This example is intentionally basic.
It only works with functions that take no arguments.
For example, this version works:
@show_before_after
def say_hello():
print("Hello!")
But this version would fail:
@show_before_after
def greet(name):
print(f"Hello, {name}!")
Why? Because wrapper() does not accept any parameters.
A more flexible decorator uses *args and **kwargs, but that is better explained on a dedicated lesson page. For the full beginner explanation, see Decorators in Python: beginner introduction.
Common beginner confusion
These points often cause confusion:
- The decorator runs when the function is defined, not only when it is later called
wrapperis the function that replaces the original name- The original function still exists as
funcinside the wrapper
In simple terms:
- Before decoration,
say_hellorefers to the original function - After decoration,
say_hellorefers towrapper - Inside
wrapper,funcstill points to the originalsay_hello
You can inspect that a little with:
print(say_hello)
print(type(say_hello))
help(say_hello)
And to run your file:
python your_script.py
Common mistakes
Here are some common problems beginners run into.
Forgetting to return wrapper
Wrong:
def show_before_after(func):
def wrapper():
print("Before function runs")
func()
print("After function runs")
This is missing:
return wrapper
Without returning wrapper, the decorated function will not be set up correctly.
Forgetting to call func() inside wrapper
Wrong:
def show_before_after(func):
def wrapper():
print("Before function runs")
print("After function runs")
return wrapper
This prints the messages, but it never runs the original function.
Adding the decorator but never calling the function
This code defines the function:
@show_before_after
def say_hello():
print("Hello!")
But nothing happens until you call:
say_hello()
Using a wrapper with no parameters on a function that needs arguments
This will cause a problem:
@show_before_after
def greet(name):
print(f"Hello, {name}!")
greet("Sam")
Your wrapper has no parameters, so it cannot accept "Sam".
Mixing up func and func()
Remember:
func= the function objectfunc()= run the function
That small difference matters a lot in Python.
FAQ
What is the simplest way to describe a decorator?
A decorator is a function that changes or extends another function.
Do I need decorators as a beginner?
Not at first, but a simple example helps you understand code you may see in real projects.
Why use @show_before_after instead of say_hello = show_before_after(say_hello)?
They do the same thing. The @ syntax is shorter and easier to read.
Why does my decorator fail when my function has parameters?
Your wrapper probably does not accept arguments. Use a wrapper that accepts *args and **kwargs.