Cómo funcionan las @ en Python
¿Qué son las @ en tu código?
¿Alguna vez has visto un @
justo antes de una función en Python y te has preguntado que hace eso ahí? ¡Bienvenido al mundo de los decoradores! Son como chefs que añaden el toque secreto a tus funciones, dándoles un sabor extra sin cambiar la receta original.
Ejemplo básico
def mayusculas(func):
def wrapper():
result = func()
return result.upper()
return wrapper
@mayusculas
def saludar():
return 'hola mundo'
print(saludar())
# HOLA MUNDO
Nuestra función saludar()
ahora devuelve el saludo en mayúsculas, gracias al decorador @mayusculas
. El decorador coge saludar()
, la envuelve con wrapper()
y nos devuelve una nueva versión de la función, todo sin tocar el código original.
Un ejemplo más interesante
Vamos a hacer algo más práctico. Digamos que quieres saber cuánto tarda una función en ejecutarse. ¡Decorador al canto!
import time
def medir_tiempo(func):
def wrapper(*args, **kwargs):
inicio = time.time()
resultado = func(*args, **kwargs)
fin = time.time()
print(f'La función {func.__name__} tardó {fin - inicio:.4f} segundos en ejecutarse.')
return resultado
return wrapper
@medir_tiempo
def procesar_datos():
time.sleep(2) # Simulamos una tarea que tarda 2 segundos
return "Datos procesados"
print(procesar_datos())
# La función procesar_datos tardó 2.0001 segundos en ejecutarse.
# Datos procesados
Ahora, cada vez que llamamos a procesar_datos()
, nuestro decorador mide el tiempo que tarda en completarse. Sin modificar el código de la función original, logramos algo súper útil.
Decoradores con Argumentos
¿Y si queremos que el decorador acepte parámetros? No hay problema. Imagina que queremos un decorador que repita la ejecución de una función varias veces.
def repetir(n):
def decorador(func):
def wrapper(*args, **kwargs):
for _ in range(n):
resultado = func(*args, **kwargs)
return resultado
return wrapper
return decorador
@repetir(3)
def decir_hola():
print('¡Hola!')
decir_hola()
# ¡Hola!
# ¡Hola!
# ¡Hola!
El decorador @repetir(3)
hace que la función decir_hola()
se ejecute 3 veces. Así de sencillo es agregar comportamiento dinámico a nuestras funciones con un simple decorador.
Conclusión
Los decoradores son una forma muy buena de extender el comportamiento de tus funciones sin tocarlas directamente. Son como agregarle superpoderes a tus funciones, pero sin alterar su ADN. Así que la próxima vez que veas un @ en Python, sabrás que algo de magia está ocurriendo ahí.