將函式體和函式呼叫關聯起來,就叫繫結
在程式執行之前(也就是編譯和鏈結時)執行的繫結是早繫結,遲繫結(late binding)是發生在執行時。
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)
情況一:上面這四種情況的輸出如下:
2 2 2
情況二:22
2情況三:
2 2 2
情況四:01
2對於情況一和情況二,沒什麼好說的,上面已經說過了,原因在於python的遲繫結。
但是,為什麼會有情況三和情況四這種情形發生呢?
首先我們應該知道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的情況。
python 踩坑系列之巢狀列表建立
初始化列表有很多方法,其中之一可以通過 來初始化 a 3 print a 通過這個方法獲取了乙個包含三個空list的巢狀列表,下面對這個列表進行修改 print a 1 1 1 通過輸出,我們發現我們只是修改了a 0 為什麼a裡的子列表全部都被修改了,接下來通過內建函式id來檢視一下a的子元素的記憶...
踩坑系列 python資料處理
最近利用python讀取txt檔案時遇到了乙個小問題,就是在計算兩個np.narray 型別的陣列時,出現了以下錯誤 typeerror ufunc subtract did not contain a loop with signature matching types dtype 作為乙個new...
Python 踩坑記錄
1.浮點數判斷 工作中遇到類似下面邏輯判斷 i 1 while i 1.5 i i 0.1 print i在想象中i應該停止在1.5就不輸出了,但是實際的輸出結果是無限迴圈。這是因為在計算機的邏輯中,浮點數的儲存規則決定了不是所有的浮點數都能準確表示,有些是不準確的,只是無限接近。如0.1轉換為二進...