Python列表推導式問題result = [lambda x: x + i for i in range(10)]

一個經典的 Python 面試題:

result = [lambda x: x + i for i in range(10)] 
print(result[0](10))

問,打印的結果是多少?
19

不止result[0](10)結果是19,result[1](10)result[2](10)result[9](10) 全是 19。

爲什麼不是 10,11…19 呢?變量 i 不是從 0 取值到 9 麼,分別再加 10。然鵝既然是面試題, 沒有坑就不好意思流傳的😂。


首先我們看這句代碼幹了啥:

result = [lambda x: x + i for i in range(10)] 

這是一個列表生成式,生成的是一個匿名函數列表。

這裏需要了解一下 Python 中函數的運行機制:

  • 遇到函數定義,直接將函數加載到內存而不會執行函數代碼。你可以簡單認爲就是把代碼原封原樣的放到內存中(實際上此時函數會生成一個內存中的對象);
  • 只有當調用時纔會實際執行函數。

這裏只是生成了匿名函數的列表而不會實際執行函數代碼,也就是說暫時並沒有生成結果。函數內部的 i 依然是隻是變量,並沒有變成具體的值,因爲此時函數並沒有執行。

只有當函數被調用時纔會實際執行函數代碼,result[0] 提取列表中的第一個匿名函數,在後面加上括號並傳入參數 result[0](10) 纔會實際調用函數,此時纔開始執行函數,纔會去找對應的變量值。

這時候就有一個問題了,i 變量在 for 循環時定義,當 for 循環完成後變量 i 的值已經變成了 9。

所以不管你取列表中的哪個函數來執行,都是同樣的結果。

如果想要結果達到你想要的 10,11…19 的話,可以在循環時就把 i 作爲參數傳進去,而不是直接使用 for 循環中的 i 變量。

result = [lambda x, i=i: x + i for i in range(10)] 
print(result[0](10))

上面的代碼,匿名函數增加了一個參數 i,並且把 i 參數的默認值設置爲 for 循環中 i 變量的值。那麼每次循環時,生成的匿名函數就會把當次循環的 i 變量的值記錄到i 參數的默認值。

這樣在後面調用時,匿名函數的 i 參數的默認值都是不同的,結果就會變成 10, 11…19 了。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章