1. 程式人生 > 實用技巧 >群友問了道3行程式碼的python面試題,有意思的題目,但是我們卻蒙了

群友問了道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,我會寫一篇匿名函式專題的文章給大家!