python 踩坑系列之遲繫結

2021-08-25 05:29:38 字數 1359 閱讀 7664

將函式體和函式呼叫關聯起來,就叫繫結

在程式執行之前(也就是編譯和鏈結時)執行的繫結是早繫結,遲繫結(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轉換為二進...