ProgramaciónDesarrollador Python

¿Cómo implementa Python el mecanismo de funciones anidadas (closures)? ¿Para qué se utilizan los closures, qué trampas existen y cómo se deben modificar las variables de la función externa correctamente?

Supere entrevistas con el asistente de IA Hintsage

Respuesta.

En Python, un closure es una función que "recuerda" los valores de las variables externas, incluso si se llamará fuera de su ámbito. Los closures se crean cuando una función interna hace referencia a variables definidas en una función externa. Para modificar tales variables desde la función anidada en Python 3, se utiliza la palabra clave nonlocal.

Ejemplo:

def make_accumulator(): total = 0 def add(value): nonlocal total total += value return total return add acc = make_accumulator() print(acc(10)) # 10 print(acc(5)) # 15

Sin nonlocal, la variable total no estaría disponible para ser modificada (error UnboundLocalError).

Pregunta trampa.

Pregunta: "¿Se puede incrementar la variable de la función externa dentro de una función anidada sin la palabra clave nonlocal?"

Respuesta: No, sin nonlocal esto provocará un error, ya que el intérprete considerará la variable como local para la función anidada. Ejemplo:

def outer(): count = 0 def inner(): count += 1 # Error UnboundLocalError return count return inner

Ejemplos de errores reales por desconocer los detalles del tema.


Historia En una aplicación web, se quería implementar un contador local para cada manejador a través de funciones anidadas, sin embargo, se olvidaron de usar nonlocal. El contador siempre devolvía 1, ya que contaba count en el espacio local y aumentaba uno nuevo, no relacionado con el closure externo.


Historia En problemas de paralelización (multithreading) a menudo se utilizan closures y lambdas. Sin comprender los closures, se creó una situación en la que todas las funciones lambda "recordaban" el último valor de la variable del ciclo, y las tareas se copiaron entre sí en lugar de procesar diferentes tareas.


Historia Al escribir un decorador sin usar un closure correcto (no se pasaron parámetros al ámbito externo), surgió una situación en la que el decorador no podía acumular estado entre llamadas, lo que llevó a resultados inesperados y a un funcionamiento inestable de la aplicación.