Skip to main content

Decoradores en Python

Introducción

Los decoradores son una característica poderosa en Python que permite modificar o extender el comportamiento de funciones o métodos sin necesidad de cambiar su código interno. Los decoradores son ampliamente utilizados en Python para agregar funcionalidades como registro, validación de entrada, memoización, y más, de manera elegante y no intrusiva.

En esta documentación, exploraremos en detalle qué son los decoradores, cómo se definen y utilizan, así como algunas de las mejores prácticas para aprovechar al máximo esta funcionalidad en Python.

Contenido

  1. ¿Qué es un Decorador?

    • Definición y concepto básico.
    • Ejemplos de uso común.
  2. Sintaxis de Decoradores

    • Definición de un decorador.
    • Aplicación de un decorador a una función.
  3. Uso de Decoradores

    • Registro de funciones.
    • Validación de entrada.
    • Memoización.
    • Otros usos comunes.
  4. Decoradores Anidados

    • Definición de decoradores anidados.
    • Ejemplos de uso.
  5. Decoradores con Argumentos

    • Definición de decoradores que aceptan argumentos.
    • Ejemplos de uso.
  6. Mejores Prácticas

    • Mantener la firma de la función original.
    • Documentar el decorador.
    • Utilizar la función functools.wraps.
    • Evitar efectos secundarios en los decoradores.

1. ¿Qué es un Decorador?

Un decorador en Python es una función que toma otra función como argumento y devuelve una nueva función modificada. Los decoradores se utilizan para extender o modificar el comportamiento de la función original sin modificar su implementación.

Los decoradores son una forma elegante de implementar patrones comunes, como la validación de entrada, el registro de funciones, la memoización, entre otros.

2. Sintaxis de Decoradores

La sintaxis básica de un decorador es la siguiente:

def decorador(funcion):
def wrapper(*args, **kwargs):
# Código antes de llamar a la función
resultado = funcion(*args, **kwargs)
# Código después de llamar a la función
return resultado
return wrapper

@decorador
def funcion_a_decorar():
# Código de la función original
pass

En este ejemplo, decorador es una función que toma otra función (funcion) como argumento y devuelve una nueva función (wrapper) que envuelve la función original. La función decorada (funcion_a_decorar) se define utilizando la sintaxis @decorador.

3. Uso de Decoradores

Los decoradores se utilizan para una variedad de propósitos, incluyendo:

  • Registro de funciones: Agregar funcionalidad de registro para rastrear el tiempo de ejecución o los argumentos de entrada/salida de una función.
  • Validación de entrada: Verificar y validar los argumentos de entrada antes de llamar a la función original.
  • Memoización: Cachear el resultado de una función para evitar recálculos costosos.

4. Decoradores Anidados

Los decoradores pueden estar anidados, lo que significa que un decorador puede aplicarse a otro decorador. Esto permite componer múltiples capas de funcionalidad en una sola función.

def decorador_externo(funcion):
def wrapper():
# Código antes de llamar a la función
resultado = funcion()
# Código después de llamar a la función
return resultado
return wrapper

def decorador_interno(funcion):
def wrapper():
# Código antes de llamar a la función
resultado = funcion()
# Código después de llamar a la función
return resultado
return wrapper

@decorador_externo
@decorador_interno
def funcion_decorada():
# Código de la función original
pass

5. Decoradores con Argumentos

Los decoradores pueden aceptar argumentos, lo que permite personalizar su comportamiento. Para definir un decorador con argumentos, se utiliza una función adicional que devuelve el decorador real.

def decorador_con_argumentos(argumento):
def decorador(funcion):
def wrapper(*args, **kwargs):
# Código antes de llamar a la función
resultado = funcion(*args, **kwargs)
# Código después de llamar a la función
return resultado
return wrapper
return decorador

@decorador_con_argumentos(argumento)
def funcion_a_decorar():
# Código de la función original
pass

6. Mejores Prácticas

Algunas mejores prácticas al utilizar decoradores incluyen:

  • Mantener la firma de la función original: El decorador debe devolver una función con la misma firma que la función original para evitar problemas de compatibilidad.
  • Documentar el decorador: Proporcionar documentación clara y concisa para el decorador para facilitar su comprensión y uso.
  • Utilizar functools.wraps: Decorar la función interna del decorador con functools.wraps para preservar los metadatos de la función original.
  • Evitar efectos secundarios: Los decoradores deben ser transparentes y no deben tener efectos secundarios inesperados en el código.

Conclusión

Los decoradores son una característica poderosa en Python que permite extender o modificar el comportamiento de las funciones de manera elegante y no intrusiva. Al comprender cómo funcionan los decoradores y seguir algunas mejores prácticas, los desarrolladores pueden aprovechar al máximo esta funcionalidad para escribir código más limpio, modular y mantenible en Python.