"Si un trabajador quiere hacer bien su trabajo, primero debe afilar sus herramientas." - Confucio, "Las Analectas de Confucio. Lu Linggong"
Página delantera > Programación > ¿Cómo manejar problemas de alcance variable en cierres Lambda no anidados?

¿Cómo manejar problemas de alcance variable en cierres Lambda no anidados?

Publicado el 2024-11-07
Navegar:435

How to Handle Variable Scoping Issues in Non-Nested Lambda Closures?

Alcance del cierre de Python Lambda

Problema

Encapsular variables dentro de cierres para eliminarlas de las firmas de funciones es una técnica que se utiliza a menudo para la estructuración eficiente del código. Sin embargo, en el caso de lambdas no anidadas, el cierre conserva el valor final de la variable, lo que genera problemas al intentar acceder a valores específicos basados ​​en la variable iterativa.

Considere el fragmento de código proporcionado:

names = ['a', 'b', 'c']

def test_fun(name, x):
    print(name, x)

def gen_clousure(name):
    return lambda x: test_fun(name, x)

funcs1 = [gen_clousure(n) for n in names]
funcs2 = [lambda x: test_fun(n, x) for n in names]

# Expected output for funcs1
for f in funcs1:
    f(1)

# Unexpected output for funcs2 (returns last element for all cases)
for f in funcs2:
    f(1)

Comprender el motivo detrás de esta discrepancia es crucial para una utilización eficaz del cierre.

Respuesta

El concepto fundamental en esta situación es alcance variable en los cierres . Los cierres contienen inherentemente los nombres de variables en lugar de sus valores. Esto significa que la evaluación de la variable ocurre cuando se inicia la ejecución lambda, en lugar de en el momento de la definición lambda.

En el caso de funcs2, cuando ejecuta lambda x: test_fun(n, x), la variable n no se evalúa durante la definición lambda. En cambio, la evaluación solo se realiza tras la llamada lambda. En ese punto, n contiene el último valor del bucle (que es 'c' en este caso). En consecuencia, la función f siempre utiliza 'c' como valor de n, independientemente de la entrada x.

Para abordar este problema y lograr la funcionalidad deseada, la variable n debe capturarse en el alcance de la función lambda. Esto se puede lograr pasando la variable como argumento a la lambda, como se muestra a continuación:

funcs2 = [lambda x: test_fun(n, x) for n in names if 2 > 0]

Al incluir esta declaración if adicional que siempre es verdadera, obligamos a la lambda a tomar el valor de n como argumento, asegurando el resultado esperado. comportamiento personalizado en todos los casos.

Alternativa con Wrapped Lambda

Alternativamente, puede envolver la lambda no anidada en una función anidada, evitando efectivamente el acceso a variables no declaradas en el alcance. El siguiente código ilustra este enfoque:

def makeFunc(n):
    return lambda x: x n

stuff = [makeFunc(n) for n in [1, 2, 3]]

for f in stuff:
    print(f(1))

Aquí, la variable n se captura en la función makeFunc, lo que garantiza un alcance adecuado dentro de la lambda.

Conclusión

Comprensión y gestión del alcance de las variables en cierres es esencial para un diseño y depuración de código efectivo. Las conclusiones clave son:

  • Los cierres contienen nombres de variables, no valores
  • La evaluación de variables se produce durante la ejecución de lambda
  • Para capturar variables, páselas como argumentos o envuélvalas la lambda en otra función
Declaración de liberación Este artículo se reproduce en: 1729483641 Si hay alguna infracción, comuníquese con [email protected] para eliminarla.
Último tutorial Más>

Descargo de responsabilidad: Todos los recursos proporcionados provienen en parte de Internet. Si existe alguna infracción de sus derechos de autor u otros derechos e intereses, explique los motivos detallados y proporcione pruebas de los derechos de autor o derechos e intereses y luego envíelos al correo electrónico: [email protected]. Lo manejaremos por usted lo antes posible.

Copyright© 2022 湘ICP备2022001581号-3