题目:
lst = [lambda x: x*i for i in range(4)]
res = [m(2) for m in lst]
print res
实际输出:[6, 6, 6, 6]
想要输出 [0, 2, 4, 6] 应该怎么改?如下:
lst = [lambda x, i=i: x*i for i in range(4)]
res = [m(2) for m in lst]
print res
这个问题涉及到了Python的闭包及延时绑定的知识(Python作用域)。
在Python核心编程里,闭包的定义如下:
如果在一个内部函数里,对外部作用域(但不是在全局作用域)的变量进行引用,那么内部函数就被认定是闭包。
总结为三点:
1、是一个内嵌函数
2、对外部函数变量引用
3、外部函数返回内嵌函数
简单的闭包例子:
def counter(start_at=0):
count = [start_at]
def incr():
count[0] += 1
return count[0]
return incr
上面的那道题,可以写成这样:
'''
遇到问题没人解答?小编创建了一个Python学习交流QQ群:778463939
寻找有志同道合的小伙伴,互帮互助,群里还有不错的视频学习教程和PDF电子书!
'''
def func():
fun_list = []
for i in range(4):
def foo(x):
return x*i
fun_list.append(foo)
return fun_list
for m in func():
print m(2)
func()是一个包含四个函数的列表:
[, , , ]
当我们执行 m(2) 时,运行到foo()内部函数,发现变量 i 并不是foo()中的变量,于是就到外部函数func中寻找变量 i ,但此时外部的 for 已经循环完毕,最后的 i =3 。所以,每次
执行m(2),i 的值都是 3 ,因此,最终结果会是 [6, 6, 6, 6] 。
当在foo()中添加 i=i 后,即:
def func():
fun_list = []
for i in range(4):
def foo(x, i=i):
return x*i
fun_list.append(foo)
return fun_list
for m in func():
print m(2)
这样的话,for循环执行时,就已经把 i(0, 1, 2, 3) 的值传给了foo()函数,此时的 i 已经是foo()函数的内部变量,运行到foo()函数时,就不会到外部函数寻找变量 i ,直接运行
x*i(0, 1, 2, 3),因此最终结果会是 [0, 2, 4, 6] 。
转自:https://blog.csdn.net/qdPython/article/details/107938206