关于python闭包 [英] About python closure
问题描述
下面是我从某人的博客中得到的一个关于python闭包的例子。
我在python 2.7运行它,并得到不同于我期望的输出。
Below is an example I got from someone's blog about python closure. I run it in python 2.7 and get a output different from my expect.
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
有没有人可以帮助解释它?
提前感谢。
My expected output is: 0, 2, 4
But the output is: 4, 4, 4
Is there anyone could help to explain it?
Thank you in advance.
推荐答案
循环不会在Python中引入范围,因此所有三个函数都关闭相同的 i
变量,并且在循环结束后将引用它的最终值,这是2。
Loops do not introduce scope in Python, so all three functions close over the same i
variable, and will refer to its final value after the loop finishes, which is 2.
似乎几乎所有我跟谁使用Python中的闭包被咬了。推论是,外部函数可以改变 i
,但内部函数不能(因为这将使 i
基于Python语法规则的闭包)。
It seems as though nearly everyone I talk to who uses closures in Python has been bitten by this. The corollary is that the outer function can change i
but the inner function cannot (since that would make i
a local instead of a closure based on Python's syntactic rules).
有两种方法可以解决这个问题:
There are two ways to address this:
# 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))
这篇关于关于python闭包的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!