1匾二、我們使用列表生成式來(lái)生成多個(gè)匿名函數(shù)
for fun in [lambda x:x*i for i in range(3)]:
print fun(2)
我們期望的返回結(jié)果是:
0
2
4
但是實(shí)際的返回結(jié)果是:
4
4
4
為什么最后生成的函數(shù)都是使用i=2這個(gè)值。
2嚼锄、我們使用函數(shù)來(lái)生成匿名函數(shù)
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
從上面的代碼可以看出亡蓉,使用函數(shù)生成的匿名函數(shù)使用的i變量是我們預(yù)期的值录豺,這是為什么呢煤傍?
我們看一下運(yùn)行時(shí)的過(guò)程:
我們從圖中可以看到盖文,使用函數(shù)生成的匿名函數(shù)中都一個(gè)變量i和值的綁定,但是在列表生成式中生成的函數(shù)就沒(méi)有和值進(jìn)行綁定蚯姆。
再來(lái)看一個(gè)例子:
def foo():
print var
if __name__ == '__main__':
foo()
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
<ipython-input-2-624891b0d01a> in <module>()
----> 1 foo()
<ipython-input-1-a40eeee590ab> in foo()
1 def foo():
----> 2 print var
3
NameError: global name 'var' is not defined
程序會(huì)輸入這樣的異常五续,說(shuō)var這個(gè)變量沒(méi)有定義,就是在python函數(shù)定義的時(shí)候龄恋,var變量只是個(gè)變量疙驾,并沒(méi)有和值綁定,只有在調(diào)用的時(shí)候才會(huì)去查找這個(gè)變量郭毕,我們?cè)趫?zhí)行函數(shù)的時(shí)候由于沒(méi)有找到這個(gè)變量的值就報(bào)錯(cuò)了
var = 12
foo()
12
所以上面使用列表生成式生成的匿名函數(shù)中它碎,i變量并沒(méi)有在函數(shù)定義的時(shí)候就和i變量的值綁定而是在調(diào)用的時(shí)候去查找i的值,這個(gè)時(shí)候由于i已經(jīng)執(zhí)行變成2,所以調(diào)用匿名函數(shù)扳肛,看到的i變量的值都是2偏竟,這也就是為什么所有的函數(shù)打印的結(jié)果都是一樣的原因。
3敞峭、解決方法
我們?cè)诙x匿名函數(shù)的時(shí)候可以顯示的給它一個(gè)默認(rèn)參數(shù)
for fun in [lambda x,i=i:x*i for i in range(3)]:
print fun(2)
0
2
4