Python ではループはスコープを導入しないため、3 つの関数はすべて同じi
変数を閉じ、ループが終了した後に最終的な値である 2 を参照します。
Python でクロージャを使用している私が話をしたほぼ全員が、これに悩まされているようです。必然的に、外側の関数は変更できますi
が、内側の関数は変更できません (これはi
、Python の構文規則に基づいてクロージャではなくローカルを作成するためです)。
これに対処するには、次の 2 つの方法があります。
# 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))