请考虑以下代码。
a = []
def func1(x):
return x
for i in range(3):
def func2():
return func1(i)
a.append(func2)
for k in range(3):
print(a[k]())
打印出来
2
2
2
从http://gestaltrevision.be/wiki/python/aliases(上一节)和http://gestaltrevision.be/wiki/python/functions_basics中'范围'部分的'使用别名',我了解到函数参数实际上是传递的参数的别名。
因此,在
中def func1(x): return x
for i in range(3):
def func2(): return func1(i)
我推断,因为x将被存储为i的别名,即使每次执行循环时都重新分配,它的别名x也无关紧要。
所以我希望前三行输出0,1,2而不是2,2,2。
你能解释一下我在这里做错了什么吗?感谢
答案 0 :(得分:2)
你在这里创建一个闭包func2,它使用封闭范围内的变量i。 func2的实例是在FOR循环执行时由DEF语句创建的。
然后在退出FOR循环后执行func2。 在python中,循环变量在循环退出后不会被销毁。 因此,在退出循环时,闭包使用封闭范围中i的当前值。
所以在这段代码中,func1什么都没有改变,如果没有它,结果就会一样。
答案 1 :(得分:2)
如果您希望代码以您希望的方式工作,请执行以下操作
def func2(i):
def func1():
return i
return func1
a = [func2(i) for i in range(3)]
for k in range(3):
print(a[k]()) # prints 0 1 2
现在,为什么你的代码没有工作?好吧,它与对象绑定到闭包中的名称时有关,func1
是。在您的代码中,参数x
到func1
在运行时被绑定。因此,a
中的每个函数都有func1(i)
且打印时i
的值为2,所以你得到所有2.所以解决方案是在编译时绑定它,即func2
1}}返回func1
,i
已绑定在func1
。
答案 2 :(得分:0)
执行此操作时:
for i in range(3):
def func2():
return func1(i)
你重新定义" func2
中每i
个[0, 1, 2]
。生活的最终定义是:
def func2():
return func1(2)
就这么简单。不幸的是,它的表现并不像你期望的那样。