Cómo utilizar los decoradores en Python

Decoradores en Python

Los decoradores en Python son una de las características más poderosas y flexibles del lenguaje. Permiten modificar el comportamiento de funciones o métodos sin alterar su código original. Si bien pueden parecer complicados al principio, su uso puede simplificar tareas repetitivas, mejorar la legibilidad y promover el código reutilizable.

En este artículo explico qué son los decoradores, por qué existen, casos de uso comunes y algunas buenas prácticas para emplearlos eficientemente.

Qué son los decoradores en Python

En términos simples, un decorador es una función que toma otra función como argumento y extiende su comportamiento sin modificarla explícitamente. En Python, esto se logra utilizando la sintaxis del símbolo @, que se coloca encima de la función a decorar.

Ejemplo básico de un decorador:

def decorador(funcion):
    def nueva_funcion(*args, **kwargs):
        print("Función decorada antes de ejecutarse")
        resultado = funcion(*args, **kwargs)
        print("Función decorada después de ejecutarse")
        return resultado
    return nueva_funcion

@decorador
def saludo(nombre):
    print(f"Hola, {nombre}")

saludo("Damián")

En la consola veremos lo siguiente:

Función decorada antes de ejecutarse
Hola, Damián
Función decorada después de ejecutarse

En este ejemplo, el decorador @decorador modifica el comportamiento de la función saludo, añadiendo código antes y después de su ejecución.

¿Por qué existen los decoradores?

Los decoradores nacen de la necesidad de reutilizar código y extender el comportamiento de funciones sin tener que modificarlas directamente. Esto es útil cuando necesitamos aplicar una funcionalidad común a varias funciones. Algunos ejemplos de esto podrían ser la autenticación de usuarios, la validación de entradas, la gestión de logs o el manejo de excepciones.

En mis clases siempre destaco la importancia de los decoradores. Desde su uso básico, hasta la versatilidad que pueden ofrecer combinados con librerías y frameworks.

Dos ejemplos claros de esto son el uso que le dan Flask y Django. En el caso de Flask un uso práctico de los decoradores es en las rutas. En Django, los decoradores se suelen emplear para agregar funcionalidades adicionales a las vistas.

Ventajas de los decoradores

A continuación veremos 3 ventajas clave a la hora de utilizar decoradores en Python:

  1. Reutilización de código. Nos permiten aplicar la misma lógica a múltiples funciones o métodos.
  2. Separación de responsabilidades. Facilitan la separación entre la lógica principal de una función y otras funcionalidades adicionales (logs, validaciones, etc.).
  3. Legibilidad. Permiten añadir o modificar comportamiento sin tener que modificar la función original.

Casos de uso comunes de decoradores en Python

A menudo, se necesita medir cuánto tiempo toma ejecutar una función. En lugar de agregar código para medir el tiempo en cada función, podemos utilizar un decorador:

import time

def medir_tiempo(funcion):
    def wrapper(*args, **kwargs):
        inicio = time.time()
        resultado = funcion(*args, **kwargs)
        fin = time.time()
        print(f"Tiempo de ejecución: {fin - inicio:.4f} segundos")
        return resultado
    return wrapper

@medir_tiempo
def funcion_ejemplo():
    time.sleep(2)
    print("Función completada")

funcion_ejemplo()

Decoradores para gestionar excepciones

Otro caso común es el manejo de excepciones. Un decorador puede encapsular este comportamiento para evitar la repetición de bloques try-except:

def manejar_excepciones(funcion):
    def wrapper(*args, **kwargs):
        try:
            return funcion(*args, **kwargs)
        except Exception as e:
            print(f"Error: {e}")
    return wrapper

@manejar_excepciones
def dividir(a, b):
    return a / b

dividir(10, 0)  # Lanza una excepción, pero es gestionada por el decorador

Buenas prácticas al usar decoradores en Python

Si bien los decoradores son útiles, demasiados decoradores pueden hacer que el código sea difícil de seguir. En mis capacitaciones destaco que hay que usarlos solo cuando añadan claridad y simplicidad al código.

Si creamos decoradores personalizados, es esencial que estén bien documentados. Esto facilitará a otros desarrolladores (o a nosotros mismos en el futuro) entender su propósito y uso.

Podemos aplicar múltiples decoradores a una misma función. Sin embargo, debemos tener cuidado con el orden. El decorador más cercano a la función es el primero en ejecutarse. Esto puede afectar el comportamiento del código si no se entiende bien.

Veamos un ejemplo:

@decorador_a
@decorador_b
def mi_funcion():
    pass

En este caso, decorador_b se ejecuta antes que decorador_a.

En conclusión

Los decoradores en Python son una herramienta poderosa para mejorar la modularidad y la reutilización de código. Ya sea para medir tiempos de ejecución, autenticar usuarios o manejar excepciones, su uso adecuado puede hacer que nuestro código sea más eficiente, legible y mantenible.

Seguir buenas prácticas es fundamental a la hora de crear un nuevo proyecto. Esto será muy importante especialmente si trabajamos en equipo. También beneficia la capacidad de escalabilidad y la mantenibilidad del código.

Más sobre Programación


Acerca de

Autor de los libros: Webmaster Profesional, HTML5: Comprenda el cambio y Apps HTML5 para móviles. Soy especialista en Desarrollo Web. Realizo proyectos basados en Inteligencia Artificial. Colaboré como autor y editor de contenidos para revistas, colecciones y diversos medios impresos y digitales. Brindo capacitaciones, clases de formación y consultorías sobre lenguajes de programación y herramientas para Desarrollo Web y móvil en modalidad online y presencial.

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

*