下面是我从某人的博客中获得的关于 python 闭包的示例。我在 python 2.7 中运行它并得到与我预期不同的输出。
flist = []
for i in xrange(3):
def func(x):
return x*i
flist.append(func)
for f in flist:
print f(2)
我的预期输出是:0、2、4
但输出是:
4、4、4 有没有人可以帮忙解释一下?
先感谢您。
循环不会在 Python 中引入作用域,因此所有三个函数都关闭同一个i
变量,并在循环结束后引用其最终值,即 2。
似乎几乎所有与我交谈过的在 Python 中使用闭包的人都被这个问题所困扰。推论是外部函数可以改变i
,但内部函数不能(因为i
根据 Python 的句法规则,这会产生局部而不是闭包)。
有两种方法可以解决这个问题:
# 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))
您没有创建闭包。您正在生成一个函数列表,每个函数i
在第一个循环后访问等于 2 的全局变量。因此,每个函数调用最终得到 2 * 2。
每个函数都访问全局i
.
from functools import partial
flist = []
for i in xrange(3):
def func(x, multiplier=None):
return x * multiplier
flist.append(partial(func, multiplier=i))