¿La función lambda no cierra el parámetro en Python?

El código habla más:

from pprint import pprint li = [] for i in range(5): li.append(lambda : pprint(i)) for k in li: k() 

rendimiento:

 4
 4
 4
 4
 4

Por qué no

 0
 1
 2
 3
 4

??

Gracias.

PD: Si escribo el decorador completo, funciona como se espera:

 from pprint import pprint li = [] #for i in range(5): #li.append(lambda : pprint(i)) def closure(i): def _func(): pprint(i) return _func for i in range(5): li.append(closure(i)) for k in li: k() 

necesitas hacer:

 lambda i=i: pprint(i) 

en lugar de capturar el valor actual de i

Hace referencia a i correctamente, solo que el momento en que se rellene su lista, tendría el valor asignado desde el último elemento de la secuencia cuando finalizó la iteración, por eso es que está viendo 4 completo.

Si no desea utilizar un argumento predeterminado, que podría introducir errores si se llama accidentalmente con un argumento, puede usar un lambda nested:

 from pprint import pprint li = [] for i in range(5): li.append((lambda x: lambda: pprint(x))(i)) for k in li: k() 

Esta es una versión anónima de su función de closure .

Las funciones lambda crean cierres sobre la variable i . Una vez finalizado el primer bucle for , i tiene valor 4 .

Luego comienza el segundo bucle for y se ejecutan todas las funciones lambda. Cada uno de ellos imprime el valor actual de i , que es 4 .

La respuesta: porque el código dentro de la lambda está usando su variable global i .

Su segunda variante hará lo mismo que la primera con lambda si elimina el parámetro i :

 def closure(): 

En lugar de

 def closure(i): 

Es decir, el código dentro de la función utilizará la variable global i .