1、我们使用列表生成式来生成多个匿名函数
for fun in [lambda x:x*i for i in range(3)]:
print fun(2)
我们期望的返回结果是:
0
2
4
但是实际的返回结果是:
4
4
4
为什么最后生成的函数都是使用i=2这个值。
2、我们使用函数来生成匿名函数
def create_fun(i):
return lambda :i
a_list = [create_fun(i) for i in range(3)]
b_list = [lambda :i for i in range(3)]
print a_list[0]()
print b_list[0]()
# 0
# 2
从上面的代码可以看出,使用函数生成的匿名函数使用的i变量是我们预期的值,这是为什么呢?
我们看一下运行时的过程:
我们从图中可以看到,使用函数生成的匿名函数中都一个变量i和值的绑定,但是在列表生成式中生成的函数就没有和值进行绑定。
再来看一个例子:
def foo():
print var
if __name__ == '__main__':
foo()
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
in ()
----> 1 foo()
in foo()
1 def foo():
----> 2 print var
3
NameError: global name 'var' is not defined
程序会输入这样的异常,说var这个变量没有定义,就是在python函数定义的时候,var变量只是个变量,并没有和值绑定,只有在调用的时候才会去查找这个变量,我们在执行函数的时候由于没有找到这个变量的值就报错了
var = 12
foo()
12
所以上面使用列表生成式生成的匿名函数中,i变量并没有在函数定义的时候就和i变量的值绑定而是在调用的时候去查找i的值,这个时候由于i已经执行变成2,所以调用匿名函数,看到的i变量的值都是2,这也就是为什么所有的函数打印的结果都是一样的原因。
3、解决方法
我们在定义匿名函数的时候可以显示的给它一个默认参数
for fun in [lambda x,i=i:x*i for i in range(3)]:
print fun(2)
0
2
4