成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

python面試題之“該死的for循環(huán)系列”(二)

shiweifu / 531人閱讀

摘要:到這里,如果你明白了,我們就可以繼續(xù)進(jìn)行下一步了理解匿名函數(shù)。

似乎只要一沾上for循環(huán),難度立刻加倍,下面我們來(lái)看一道python的面試題:

要求寫(xiě)出下面代碼的輸出結(jié)果并且解釋原因。

def multipliers():
    return [lambda x:i*x for i in range(4)]
print([m(2) for m in multipliers()])

這道題涉及的知識(shí)點(diǎn)包括以下幾個(gè)方面:

1、列表推導(dǎo)式
2、匿名函數(shù)
3、閉包函數(shù)
4、for循環(huán)對(duì)函數(shù)的迭代調(diào)用
5、閉包函數(shù)的調(diào)用

首先我們來(lái)說(shuō)一下列表推導(dǎo)式,只有深入理解列表推導(dǎo)式,我們才能理解下面這句話到底干了些什么事情[lambda x:i*x for i in range(4)]
引用官方文檔中對(duì)于列表推導(dǎo)式的一個(gè)例子:squares = [x2 for x in range(10)] 這個(gè)列表推導(dǎo)式返回的結(jié)果為[0, 1, 4, 9, 16, 25, 36, 49, 64, 81],for循環(huán)通過(guò)對(duì)range(10)進(jìn)行迭代后得到每個(gè)x的值,然后對(duì)它進(jìn)執(zhí)行x2的操作,最終結(jié)果為一個(gè)列表
那么如果不用列表推導(dǎo)式如何達(dá)到這個(gè)目的呢?答案如下,這個(gè)列表推導(dǎo)式等同于下面的代碼:

squares = []
for x in range(10):
    squares.append(x**2)

這段代碼執(zhí)行后,squares的結(jié)果一樣是[0, 1, 4, 9, 16, 25, 36, 49, 64, 81],根據(jù)這個(gè)例子我們可以簡(jiǎn)單地認(rèn)為列表推導(dǎo)式是這樣工作的:首先它會(huì)定義一個(gè)空列表,然后根據(jù)設(shè)定的條件得到一個(gè)一個(gè)的元素,同時(shí)把元素添加進(jìn)列表中。

現(xiàn)在回到我們這道題,來(lái)看一下本題中的[lambda x:i*x for i in range(4)]這個(gè)列表推導(dǎo)式,如果把它拆開(kāi)來(lái)的話它等價(jià)于下面的這段代碼:

squares = []
for i in range(4):
    res = lambda x:i*x
    squares.append(res)

最終squares就是列表推導(dǎo)式的結(jié)果(一個(gè)列表),然后我們?cè)傺芯肯逻@個(gè)列表中的元素都是什么。
到這里,如果你明白了,我們就可以繼續(xù)進(jìn)行下一步了——理解匿名函數(shù)。

匿名函數(shù)的關(guān)鍵字為lambda,表現(xiàn)形式為:lambda 參數(shù) : 返回值,lambda后面的參數(shù)就是函數(shù)的形參,冒號(hào)后面的表達(dá)式就是返回值。
比如:lambda a, b: a+b 這個(gè)簡(jiǎn)單的匿名函數(shù)可以傳入兩個(gè)參數(shù)a和b,結(jié)果返回a+b,這里要記住,只有調(diào)用這個(gè)匿名函數(shù),它才會(huì)執(zhí)行冒號(hào)后面的代碼,這也是函數(shù)的執(zhí)行法則,只有被調(diào)用時(shí),函數(shù)內(nèi)部的命名空間才會(huì)生效,在被調(diào)用之前它就是一個(gè)函數(shù)名指向的內(nèi)存地址而已。

匿名函數(shù)雖然是匿名的,但是它也可以有名字,也可以作為一個(gè)結(jié)果賦值給任意的變量,所以它顯然可以成為一個(gè)函數(shù)的返回值,也可以變成一個(gè)列表的元素,只不過(guò)此時(shí)這個(gè)列表的元素是匿名函數(shù)對(duì)應(yīng)的內(nèi)存地址罷了。見(jiàn)下面的例子:

#匿名函數(shù)直接賦值給變量lam
lam = lambda a,b:a+b
#此時(shí)lam指向了匿名函數(shù)的內(nèi)存地址
print(lam)#此時(shí)的lam就是一個(gè)內(nèi)存地址: at 0x7fecdc6b7e18>
res = lam(2,5) #調(diào)用匿名函數(shù),把結(jié)果賦值給res
print(res)
 at 0x7fecdc6b7e18>
7

接下來(lái)我們說(shuō)一下閉包,當(dāng)前函數(shù)引用到上一層函數(shù)的局部命名空間的變量時(shí)就會(huì)觸發(fā)閉包規(guī)則。我們說(shuō)觸發(fā)了閉包的函數(shù)叫做閉包函數(shù),但是要注意一點(diǎn):只有當(dāng)調(diào)用閉包函數(shù)的時(shí)候它才會(huì)去引用外層函數(shù)的變量,因?yàn)樵谡{(diào)用閉包函數(shù)之前,閉包內(nèi)部的命名空間還不存在。

然后我們回頭看這道題的代碼:

def multipliers():
    return [lambda x:i*x for i in range(4)]
print([m(2) for m in multipliers()])
#根據(jù)前面的敘述,我們可以把它改成容易理解的形式:
def multipliers():
    squares = []
    for i in range(4):
        res = lambda x:i*x
        squares.append(res)
    return squares
print([m(2) for m in multipliers()])

匿名函數(shù)lambda x:i*x引用了外層函數(shù)multipliers()的命名空間內(nèi)的變量i,所以它觸發(fā)了閉包規(guī)則,然后函數(shù)multipliers()的返回值是一個(gè)列表,這個(gè)列表的元素為四個(gè)閉包函數(shù)名指向的內(nèi)存地址,雖然for i in range(4)這段代碼里面的i的值分別被賦予了 0 1 2 3這四個(gè)值,但是閉包函數(shù)res并沒(méi)有引用這四個(gè)值,因?yàn)殚]包函數(shù)此時(shí)此刻還沒(méi)有被真正調(diào)用,列表推導(dǎo)式僅僅是把四個(gè)匿名函數(shù)指向的內(nèi)存地址保存在了一個(gè)列表里,因?yàn)闆](méi)有調(diào)用,所以匿名函數(shù)內(nèi)部的代碼并沒(méi)有執(zhí)行,也就不存在引用。
所以函數(shù)multipliers()的返回值就是這樣的一個(gè)列表:[lambda x:ix,lambda x:ix,lambda x:ix,lambda x:ix]

我們來(lái)看最后一條語(yǔ)句print([m(2) for m in multipliers()])
for m in multipliers() 這條語(yǔ)句到底干了什么?其實(shí)它干的事情只有一個(gè),那就是遍歷了函數(shù)multipliers()返回的列表,在遍歷列表的同時(shí)把每個(gè)匿名函數(shù)賦值給了m,把它拆分來(lái)看就是這樣:
m = lambda x:i*x
m = lambda x:i*x
m = lambda x:i*x
m = lambda x:i*x
并且每次都執(zhí)行了一次 m(2),也就是每次都調(diào)用了一下匿名函數(shù),注意:此時(shí)此刻匿名函數(shù)才真正被調(diào)用了,然后它會(huì)引用外層命名空間的變量i,那么此時(shí)i的值是多少呢?
因?yàn)閒or i in range(4)這個(gè)for循環(huán)已經(jīng)執(zhí)行完畢,i的值等于3,所以每次當(dāng)執(zhí)行m(2)時(shí),i的值都等于3
所以每次調(diào)用m(2)的結(jié)果都是6
最終輸出結(jié)果為[6, 6, 6, 6]

def multipliers():
    return [lambda x:i*x for i in range(4)]
print([m(2) for m in multipliers()])
[6, 6, 6, 6]

把這道面試題中的所有列表推導(dǎo)式拆開(kāi)的話 它應(yīng)該是下面這個(gè)樣子,結(jié)果完全一樣:
def multipliers():
    squares = []
    for i in range(4):
        res = lambda x:i*x
        squares.append(res)
    return squares

#print(multipliers()),此時(shí)此刻如果我們打印一下這個(gè)函數(shù),也就是調(diào)用一下看看返回結(jié)果,你會(huì)發(fā)現(xiàn),它就是一個(gè)由四個(gè)函數(shù)內(nèi)存地址組成的列表:
"""[. at 0x7fecdc6de2f0>, 
 . at 0x7fecdc6de510>, 
 . at 0x7fecdc6de158>, 
 . at 0x7fecdc6de268>]"""

squares2 = []
for m in multipliers():
    squares2.append(m(2))
print(squares2)
[6, 6, 6, 6]

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/42558.html

相關(guān)文章

  • python面試題之該死for循環(huán)系列”(一)

    摘要:這是一道魔性面試題,難倒了無(wú)數(shù)英雄好漢上面代碼的執(zhí)行順序是這樣的從上到下第一個(gè)函數(shù)就是實(shí)現(xiàn)了一個(gè)簡(jiǎn)單的加法運(yùn)算第二個(gè)函數(shù)是一個(gè)生成器函數(shù),如果調(diào)用它會(huì)返回一個(gè)生成器這一行調(diào)用了生成器函數(shù),所以此刻就是一個(gè)生成器它的本質(zhì)還是迭代器然后執(zhí)行循環(huán) 這是一道魔性面試題,難倒了無(wú)數(shù)英雄好漢…… def add(n,i): return n+i def test(): for i...

    wudengzan 評(píng)論0 收藏0
  • 數(shù)據(jù)分析面試題之Pandas中groupby

    摘要:昨天晚上,筆者有幸參加了一場(chǎng)面試,有一個(gè)環(huán)節(jié)就是現(xiàn)場(chǎng)編程題目如下示例數(shù)據(jù)如下,求每名學(xué)生對(duì)應(yīng)的成績(jī)最高的那門(mén)科目與,用實(shí)現(xiàn)這個(gè)題目看上去很簡(jiǎn)單,其實(shí),并不簡(jiǎn)單。 ??昨天晚上,筆者有幸參加了一場(chǎng)面試,有一個(gè)環(huán)節(jié)就是現(xiàn)場(chǎng)編程!題目如下:??示例數(shù)據(jù)如下,求每名學(xué)生(ID)對(duì)應(yīng)的成績(jī)(score)最高的那門(mén)科目(class)與ID,用Python實(shí)現(xiàn): showImg(https://se...

    ThinkSNS 評(píng)論0 收藏0
  • 用9種辦法解決 JS 閉包經(jīng)典面試題之 for 循環(huán)取 i

    摘要:閉包正確的說(shuō)應(yīng)該是指一個(gè)閉包域每當(dāng)聲明了一個(gè)函數(shù)它就產(chǎn)生了一個(gè)閉包域可以解釋為每個(gè)函數(shù)都有自己的函數(shù)棧每個(gè)閉包域?qū)ο蠖加幸粋€(gè)不是屬性內(nèi)默認(rèn)有個(gè)名為的全局引用有了這個(gè)引用就可以直接調(diào)用的屬性或方法凡是在閉包域內(nèi)聲明的變量或方法外部無(wú)法直接訪問(wèn) 閉包 正確的說(shuō),應(yīng)該是指一個(gè)閉包域,每當(dāng)聲明了一個(gè)函數(shù),它就產(chǎn)生了一個(gè)閉包域(可以解釋為每個(gè)函數(shù)都有自己的函數(shù)棧),每個(gè)閉包域(Function...

    Betta 評(píng)論0 收藏0
  • JS面試題之比較兩個(gè)對(duì)象是否相等?

    摘要:這是我在一次面試中,被面試官所提問(wèn)的一道題在這次面試題中相等指的是對(duì)象的屬性個(gè)數(shù)值相等有這樣兩個(gè)李德華張德華我能想到的一種方案解答過(guò)程的思考由于沒(méi)有,我只能通過(guò)轉(zhuǎn)化成數(shù)組進(jìn)入第二步,對(duì)象中的屬性在另一個(gè)中是否存在。 這是我在一次面試中,被面試官所提問(wèn)的一道題 在這次面試題中 相等:指的是對(duì)象的屬性個(gè)數(shù)值相等 有這樣兩個(gè)obj let obj1 = { name:李德華, ...

    wangbjun 評(píng)論0 收藏0
  • 你不能錯(cuò)過(guò)前端面試題合集

    摘要:收集的一些前端面試題從面試題發(fā)現(xiàn)不足,進(jìn)而查漏補(bǔ)缺,比通過(guò)面試更難得及各大互聯(lián)網(wǎng)公司前端筆試面試題篇及各大互聯(lián)網(wǎng)公司前端筆試面試題篇面試題個(gè)和個(gè)經(jīng)典面試題前端開(kāi)發(fā)面試題如何面試前端工程師很重要個(gè)變態(tài)題解析如何通過(guò)餓了么面試輕 收集的一些前端面試題 從面試題發(fā)現(xiàn)不足,進(jìn)而查漏補(bǔ)缺,比通過(guò)面試更難得 1 BAT及各大互聯(lián)網(wǎng)公司2014前端筆試面試題--Html,Css篇 2 BAT...

    ninefive 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<