群友問了道3行程式碼的python面試題,有意思的題目,但是我們卻蒙了
本文的文字及圖片來源於網路,僅供學習、交流使用,不具有任何商業用途,版權歸原作者所有,如有問題請及時聯絡我們以作處理
以下文章來源於騰訊雲 作者:Python進擊者
( 想要學習Python?Python學習交流群:1039649593,滿足你的需求,資料都已經上傳群檔案流,可以自行下載!還有海量最新2020python學習資料。 )
有意思的題目
題目:寫出下面程式執行結果
def multipliers(): return [lambda x:i*x for i in range(4)] print([m(2) for m in multipliers()])
正確答案:
[6,6,6,6]
第一眼看,不就是匿名函式嗎?但是仔細想想匿名函式在平時的開發中沒怎麼用,所以也忘的差不多了。例如那個m(2)當時就不懂是啥意思了。
好,我們就來看看這個題目,首先第一段程式碼:
def multipliers(): return [lambda x:i*x for i in range(4)]
這是一個典型的列表推導式,簡而言之就是在列表中推導計算並且將計算的結果放入列表,上面這串程式碼我們可以寫成:
squares = [] for i in range(4): res = lambda x:i*x squares.append(res)
這樣可能看的更加的簡單明瞭。但是這裡面也有一個匿名函式,計算i*x的值,如果大家對匿名函式不太懂的,可以去翻閱相關資料瞭解一下。
我們接下來看這段程式碼:
print([m(2) for m in multipliers()])
其實這段程式碼也很好理解,m(2)的意思就是將2作為引數傳入上面的匿名函式當中,但是為什麼結果等於[6,6,6,6]呢?
我們來debug一下看看:
斷點,開始debug
跳到了multipliers函式當中
仍然在迴圈體中
執行到3,迴圈即將結束
跳轉下來
重新進入匿名函式計算
def multipliers(): squares = []for i in range(4): res = lambda x:i*x squares.append(res)
我們用這種方法來看待這個閉包函式lambda x:ix,為什麼稱它為閉包函式呢?因為當執行lambda x:ix這串程式碼時呼叫了上一層函式multipliers()的區域性名稱空間的變數i,所以此處是閉包函式。
但是此時的列表中並不是匿名函式計算出來的值,因為此時還沒有被呼叫,此時列表中只是有四個匿名函式的記憶體地址:
[<function multipliers.<locals>.<lambda> at 0x1057d1710>, <function multipliers.<locals>.<lambda> at 0x10586dd40>, <function multipliers.<locals>.<lambda> at 0x10586de60>, <function multipliers.<locals>.<lambda> at 0x10586df80>]
那什麼時候才算真正呼叫呢?在上面我們講過
print([m(2) for m in multipliers()])
這串程式碼將2作為引數傳入上面的匿名函式當中,此時也就是呼叫了匿名函式。當去呼叫的時候,for i in range(4)這個迴圈已經執行完畢,此時的i已經是3了,所以就有了最後的結果:
[6,6,6,6
總結
其實很多題目都是出自一些我們平時不是很重視的知識點上,但是往往這些知識點非常重要。所以學習的時候,對於重點知識不能因為不使用它而去遺忘,而是要多去看看。非常感謝大家能夠看完這篇文章,如果在看數超過30,我會寫一篇匿名函式專題的文章給大家!