Decorators in Python

Python Decorators

Decorators are a way we can use higher order functions to modify other functions. Typically they are used to wrap a function with another function.


def hello(name="Ian"):
    def greeting(func):
        def wrapper(*args, **kwargs):
            print("A man is sitting at the bar, you go up and greet him.")

            if name == "Ian":
                print("My name is Ian, what's yours?")
            else:
                print(f"My name is {name}, what's yours?")

            print("The man glances your way momentarily, then moves to the other end of the bar.")
            result = func(*args, **kwargs)
            return result
        return wrapper
    return greeting

@hello("Alice")
def bar_talk():
    print("You start a conversation about the weather with the bartender instead.")

@hello()
def another_chat():
    print("You shrug your shoulders and ask the bartender about the local sports team.")


print("=== First Interaction ===")
bar_talk()

print("\n=== Second Interaction ===")
another_chat()

In the example above, you would get the following print out:

=== First Interaction ===
A man is sitting at the bar, you go up and greet him.
My name is Alice, what's yours?
The man glances your way momentarily, then moves to the other end of the bar.
You start a conversation about the weather with the bartender instead.

=== Second Interaction ===
A man is sitting at the bar, you go up and greet him.
My name is Ian, what's yours?
The man glances your way momentarily, then moves to the other end of the bar.
You shrug your shoulders and ask the bartender about the local sports team.

What’s Actually Happening?

When you called bar_talk(), Python encounters @hello("Alice"), which calls hello("Alice") and returns the greeting function.

Second, greeting(bar_talk) is called, which returns the wrapper function. wrapper is then assigned to decorate bar_talk and gets to work.

wrapper then works line by line and prints “A man is sitting at the bar…”, checks the argument passed into greeting for the name given (“Alice”), and chooses the else option, since the if option failed. This prints “My name is Alice…”

It then finishes the wrapper function by printing “The man glances…” line and returns all those arguments to the outer functions.

Finally, the bar_talk function is called, having been successfully decorated or wrapped by the hello function. This prints “You start a conversation…”

🧠 When you use decorators, you tell Python to wrap the function immediately following the @decorator with the decorator function.

When you later call the function to be decorated, Python first calls the innermost (wrapper) function and then the function you wanted to be decorated.

Real Life Uses

In real life coding scenarios, decorators are commonly used for logging, authentication, timing, and caching purposes.