Curso de Python / Comprender decoradores y gestores de contexto
Un decorador envuelve el comportamiento de una llamada a función; un gestor de contexto controla la preparación y limpieza de un bloque. Ambos permiten extraer infraestructura repetida, siempre que se mantengan deliberadamente los contratos de retorno, argumentos y excepciones.
Separar envoltura y duración de recursos
@decorator aplica una función decoradora a la función definida y asigna su resultado al nombre de esta. Es código ejecutable, no un comentario. En cambio, with organiza la entrada y salida de un contexto y puede asegurar limpieza cuando el cuerpo genera una excepción.
functools.wraps conserva metadatos como el nombre y la documentación de la función original. No demuestra que el envoltorio preserve automáticamente todas las garantías de tipos, seguridad o gestión de errores. Esa responsabilidad sigue siendo del código que escribes.
Ejecutar un envoltorio y una colección temporal
Guarda el siguiente programa completo como wrappers.py y ejecútalo con python wrappers.py. functools y contextlib forman parte de la biblioteca estándar.
from functools import wraps
from contextlib import contextmanager
def announce(func):
@wraps(func)
def wrapper(*args, **kwargs):
print("start")
return func(*args, **kwargs)
return wrapper
@contextmanager
def temporary_items():
items = []
try:
yield items
finally:
items.clear()
print("cleared")
@announce
def total(amounts):
return sum(amounts)
with temporary_items() as items:
items.extend([3500, 8000])
print(total(items))
print(total.__name__)
print(items)
start
11500
cleared
total
[]
La llamada decorada anuncia start y conserva el retorno de la suma. Al salir del bloque, el contexto vacía la lista e imprime cleared. Gracias a wraps, el nombre consultado sigue siendo total. La referencia items continúa existiendo, pero su lista ya está vacía.
Seguir retornos y excepciones entre capas
En términos de transformación, decorar total con announce equivale a asignar total = announce(total) después de definirla. El envoltorio recibe *args y **kwargs y reenvía los argumentos. Si omite return, cambia el resultado visible a None, aunque la función interna calcule correctamente.
Una función decorada con contextmanager cede el control una vez mediante yield. Al terminar el bloque, vuelve a ejecutarse para completar la salida. La limpieza está en finally para que ocurra también ante un fallo. Capturar una excepción alrededor de yield sin volver a lanzarla puede suprimirla; decide explícitamente si eso representa una recuperación válida.
La referencia de contextmanager detalla ese flujo, y la referencia de wraps explica los metadatos conservados. Los fundamentos están en las excepciones y finally y los generadores.
Comprobar limpieza y elegir la abstracción
- Lanza un
ValueErrordeliberado dentro delwith. Captúralo fuera y verifica que se ejecuta la limpieza. - Inspecciona la lista después de salir para confirmar que está vacía.
- Retira temporalmente el
returndel envoltorio, compara el resultado y restáuralo.
No confundas limpieza con reintento. Un decorador que repite una petición con efectos puede duplicar transacciones. Su política de intentos, demoras e idempotencia necesita otro diseño. Para una operación pequeña que solo aparece una vez, un bloque directo puede resultar más fácil de comprender que introducir una nueva abstracción.




