Hacemos una revisión exhaustiva cada secciones de nuestro espacio con el objetivo de mostrarte en todo momento información veraz y actual.
Solución:
Python en realidad se está comportando como se define. Tres funciones separadas son creados, pero cada uno tiene la cierre del entorno en el que están definidos – en este caso, el entorno global (o el entorno de la función externa si el ciclo se coloca dentro de otra función). Sin embargo, este es exactamente el problema: en este entorno, estoy mutadoy los cierres todos referirse a la misma yo.
Esta es la mejor solución que se me ocurre: crear un creador de funciones e invocar que en cambio. esto obligará diferentes ambientes para cada una de las funciones creadas, con un diferente yo en cada uno.
flist = []
for i in xrange(3):
def funcC(j):
def func(x): return x * j
return func
flist.append(funcC(i))
for f in flist:
print f(2)
Esto es lo que sucede cuando mezclas efectos secundarios y programación funcional.
Las funciones definidas en el bucle siguen accediendo a la misma variable i
mientras cambia su valor. Al final del bucle, todas las funciones apuntan a la misma variable, que contiene el último valor del bucle: el efecto es el que se informa en el ejemplo.
En orden para evaluar i
y usar su valor, un patrón común es establecerlo como un parámetro predeterminado: los parámetros predeterminados se evalúan cuando el def
se ejecuta la instrucción y, por lo tanto, el valor de la variable de bucle se congela.
Lo siguiente funciona como se esperaba:
flist = []
for i in xrange(3):
def func(x, i=i): # the *value* of i is copied in func() environment
return x * i
flist.append(func)
for f in flist:
print f(2)
Así es como lo hace usando el functools
biblioteca (que no estoy seguro de que estuviera disponible en el momento en que se planteó la pregunta).
from functools import partial
flist = []
def func(i, x): return x * i
for i in xrange(3):
flist.append(partial(func, i))
for f in flist:
print f(2)
Salidas 0 2 4, como se esperaba.