logo

Writing Your First Decorator

So, you've heard about decorators, but they seem a bit magical? Let's break them down. At its core, a decorator is just a function that takes another function and returns a new function.

Think of it like gift wrapping. The gift (your original function) is inside, but now it has a nice wrapper around it (the decorator) that adds something extra before you even open it.

Here is the standard "recipe" for writing one:

def my_decorator(func):
    # This wrapper function is the "gift wrap"
    def wrapper():
        print("🎁 Something is happening before the function is called.")
        func()
        print("🎉 Something is happening after the function is called.")
    return wrapper

See what happened there? We defined a function wrapper inside my_decorator. This wrapper adds some print statements and calls the original func. Finally, my_decorator returns this new wrapper function.

Now, let's use it! You attach it to a function using the @ symbol:

@my_decorator
def say_hello():
    print("Hello!")

When you call say_hello(), you're actually running the wrapper function we defined earlier:

say_hello()

Output:

🎁 Something is happening before the function is called.
Hello!
🎉 Something is happening after the function is called.

The @my_decorator syntax is just a shortcut. Without it, you would have to write say_hello = my_decorator(say_hello). The @ syntax just makes your code look much cleaner!

This pattern is incredibly powerful for things like logging, timing how long code takes to run, or checking if a user is logged in before they can access a page.

I walk through this pattern step-by-step and show you how to build real-world decorators in my Python Decorators course.