decoradores-en-python

What are decorators and how to use them in Python

  • 2 min

In Python, a decorator is a function that receives another function as an argument and returns a new function that, generally, extends the behavior of the original one.

Decorators allow modifying or extending the behavior of functions or methods without modifying their source code.

They are widely used for cross-cutting concerns such as authentication, logging, and validation, among others.

Defining a decorator

Let’s see it with an example

def my_decorator(func):
    def wrapper():
        print("Something is done before the function")
        func()
        print("Something is done after the function")
    return wrapper
Copied!

In this example

  • my_decorator is a function that receives a function func
  • Inside it defines a function wrapper (it could have any name)
  • The wrapper function uses the received function func
  • Finally my_decorator returns the wrapper function

Using a decorator

Now, to use the decorator the symbol @ followed by the decorator’s name is used, before the definition of the function to be decorated.

@my_decorator
def greet():
    print("Hello from LuisLlamas.es!")

greet()

# Output:
# Something is done before the function
# Hello from LuisLlamas.es!
# Something is done after the function
Copied!

In this example:

  • When greet is invoked, my_decorator actually “takes control”
  • my_decorator receives the greet function, and returns the wrapper function that uses it
  • This adds behavior before and after the execution of greet

Decorators with arguments

Decorators can also accept arguments. To do this, functions need to be nested:

  • An outer function to accept the decorator’s arguments
  • An inner function that accepts the function to be decorated.

For example,

def repeat(n):
    def decorator(func):
        def wrapper(*args, **kwargs):
            for _ in range(n):
                func(*args, **kwargs)
        return wrapper
    return decorator

@repeat(3)
def say_goodbye():
    print("Goodbye!")

say_goodbye()

# Output:
# Goodbye!
# Goodbye!
# Goodbye!
Copied!

In this case,

  • repeat is a decorator that accepts an argument n
  • It repeats the execution of the decorated function n times

Multi-level decorators

Python allows nesting decorators, applying multiple decorators to the same function.

def decorator1(func):
    def wrapper():
        print("Decorator 1 before")
        func()
        print("Decorator 1 after")
    return wrapper

def decorator2(func):
    def wrapper():
        print("Decorator 2 before")
        func()
        print("Decorator 2 after")
    return wrapper

@decorator1
@decorator2
def function():
    print("Function is running")

function()

# Output:
# Decorator 1 before
# Decorator 2 before
# Function is running
# Decorator 2 after
# Decorator 1 after
Copied!

In this example, function is decorated first by decorator2 and then by decorator1, showing how multiple decorators can be chained.