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_after takes a function as input
  • It defines a new function called wrapper
  • wrapper runs extra code
  • wrapper also 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_name syntax 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:

  • func means the function itself
  • func() 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:

  1. The decorator runs code before
  2. The original function runs
  3. 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
  • wrapper is the function that replaces the original name
  • The original function still exists as func inside the wrapper

In simple terms:

  • Before decoration, say_hello refers to the original function
  • After decoration, say_hello refers to wrapper
  • Inside wrapper, func still points to the original say_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 object
  • func() = 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.

See also #

Press Esc to close