Loops no introducen alcance en Python, por lo que las tres funciones cierre durante el mismo i
variable y se referirá a su valor final después de que finalice bucle, que es 2.
Parece que casi todo el mundo me hablar con quién usa cierres en Python ha sido mordido por esto. El corolario es que la función externa puede cambiar i
pero la función interna no puede (ya que eso haría que i
sea un local en lugar de un cierre basado en las reglas sintácticas de Python).
Hay dos maneras de abordar este:
# avoid closures and use default args which copy on function definition
for i in xrange(3):
def func(x, i=i):
return x*i
flist.append(func)
# or introduce an extra scope to close the value you want to keep around:
for i in xrange(3):
def makefunc(i):
def func(x):
return x*i
return func
flist.append(makefunc(i))
# the second can be simplified to use a single makefunc():
def makefunc(i):
def func(x):
return x*i
return func
for i in xrange(3):
flist.append(makefunc(i))
# if your inner function is simple enough, lambda works as well for either option:
for i in xrange(3):
flist.append(lambda x, i=i: x*i)
def makefunc(i):
return lambda x: x*i
for i in xrange(3):
flist.append(makefunc(i))
posible duplicado de [cierres léxicos en Python] (http://stackoverflow.com/questions/233673/lexical-closures-in-python) – BrenBarn