將函數體和函數調用關聯起來,就叫綁定html
在程序運行以前(也就是編譯和連接時)執行的綁定是早綁定,遲綁定(late binding)是發生在運行時。python
def outer(): return [lambda x: x*i for i in range(3)] f1, f2, f3 = outer() print f1(1) print f2(1) print f3(1) >>> 2 >>> 2 >>> 2
咋一看,上面輸出的值貌似和本身想的並不一致,爲何會出現這個問題,這就是python的遲綁定致使的,閉包中的i值只有在調用匿名函數的時候纔會去查詢,這就致使了當你在調用f1,f2,f3的時候此時i的值已變成2,因此它們的輸出結果都是同樣的。閉包
咱們再來看看這個問題的變形。函數
#狀況一 l = [lambda x: x*i for i in range(3)] f1, f2, f3 = l print f1(1),f2(1),f3(1) #狀況二 l = [lambda x: x*i for i in range(3)] for f in l: print f(1) #狀況三 l = (lambda x: x*i for i in range(3)) f1, f2, f3 = l print f1(1),f2(1),f3(1) #狀況四 l = (lambda x: x*i for i in range(3)) for f in l: print f(1)
狀況一:上面這四種狀況的輸出以下:post
2 2 2spa
狀況二:
2
2
2code
狀況三:
2 2 2htm
狀況四:
0
1
2blog
對於狀況一和狀況二,沒什麼好說的,上面已經說過了,緣由在於python的遲綁定。it
可是,爲何會有狀況三和狀況四這種情形發生呢?
首先咱們應該知道python生成器的表達式,相似於列表推導,只不過是圓括號,
(lambda x: x*i for i in range(3))實際上是一個生成器,咱們先說一下爲何狀況四和上面三種都不同,生成器只有在調用next()時纔會執行下去,因此在對這個生成器進行for迭代時,迭代一次,i的值變化一次,因此輸出結果纔會有0,1,2的變化。
爲何狀況三沒有這個變化呢?
l = (lambda x: x*i for i in range(3)),f1, f2, f3 = l,在對f1,f2,f3進行賦值時,已所有迭代完了,此時i的值爲2,因此會出現輸出值全是2的狀況。