徹底理解Python中的yield關(guān)鍵字
閱讀別人的python源碼時(shí)碰到了這個(gè)yield這個(gè)關(guān)鍵字,各種搜索終于搞懂了,在此做一下總結(jié):
- 通常的for...in...循環(huán)中,in后面是一個(gè)數(shù)組,這個(gè)數(shù)組就是一個(gè)可迭代對(duì)象,類似的還有鏈表,字符串,文件。它可以是mylist = [1, 2, 3],也可以是mylist = [x*x for x in range(3)]。它的缺陷是所有數(shù)據(jù)都在內(nèi)存中,如果有海量數(shù)據(jù)的話將會(huì)非常耗內(nèi)存。
- 生成器是可以迭代的,但只可以讀取它一次。因?yàn)橛玫臅r(shí)候才生成。比如 mygenerator = (x*x for x in range(3)),注意這里用到了(),它就不是數(shù)組,而上面的例子是[]。
- 我理解的生成器(generator)能夠迭代的關(guān)鍵是它有一個(gè)next()方法,工作原理就是通過重復(fù)調(diào)用next()方法,直到捕獲一個(gè)異常。可以用上面的mygenerator測(cè)試。
- 帶有 yield 的函數(shù)不再是一個(gè)普通函數(shù),而是一個(gè)生成器generator,可用于迭代,工作原理同上。
- yield 是一個(gè)類似 return 的關(guān)鍵字,迭代一次遇到y(tǒng)ield時(shí)就返回yield后面(右邊)的值。重點(diǎn)是:下一次迭代時(shí),從上一次迭代遇到的yield后面的代碼(下一行)開始執(zhí)行。
- 簡(jiǎn)要理解:yield就是 return 返回一個(gè)值,并且記住這個(gè)返回的位置,下次迭代就從這個(gè)位置后(下一行)開始。
- 帶有yield的函數(shù)不僅僅只用于for循環(huán)中,而且可用于某個(gè)函數(shù)的參數(shù),只要這個(gè)函數(shù)的參數(shù)允許迭代參數(shù)。比如array.extend函數(shù),它的原型是array.extend(iterable)。
- send(msg)與next()的區(qū)別在于send可以傳遞參數(shù)給yield表達(dá)式,這時(shí)傳遞的參數(shù)會(huì)作為yield表達(dá)式的值,而yield的參數(shù)是返回給調(diào)用者的值。——換句話說,就是send可以強(qiáng)行修改上一個(gè)yield表達(dá)式值。比如函數(shù)中有一個(gè)yield賦值,a = yield 5,第一次迭代到這里會(huì)返回5,a還沒有賦值。第二次迭代時(shí),使用.send(10),那么,就是強(qiáng)行修改yield 5表達(dá)式的值為10,本來是5的,那么a=10
- send(msg)與next()都有返回值,它們的返回值是當(dāng)前迭代遇到y(tǒng)ield時(shí),yield后面表達(dá)式的值,其實(shí)就是當(dāng)前迭代中yield后面的參數(shù)。
- 第一次調(diào)用時(shí)必須先next()或send(None),否則會(huì)報(bào)錯(cuò),send后之所以為None是因?yàn)檫@時(shí)候沒有上一個(gè)yield(根據(jù)第8條)??梢哉J(rèn)為,next()等同于send(None)。
代碼示例1:
#encoding:UTF-8 def yield_test(n): for i in range(n): yield call(i) print("i=",i) #做一些其它的事情 print("do something.") print("end.") def call(i): return i*2 #使用for循環(huán) for i in yield_test(5): print(i,",")
結(jié)果是:
>>>
0 ,
i= 0
2 ,
i= 1
4 ,
i= 2
6 ,
i= 3
8 ,
i= 4
do something.
end.
>>>
理解的關(guān)鍵在于:下次迭代時(shí),代碼從yield的下一跳語句開始執(zhí)行。
代碼示例2:
def node._get_child_candidates(self, distance, min_dist, max_dist): if self._leftchild and distance - max_dist < self._median: yield self._leftchild if self._rightchild and distance + max_dist >= self._median: yield self._rightchild
與前面不同的是,這個(gè)函數(shù)中沒有for循環(huán),但它依然可以用于迭代。
node._get_child_candidates
函數(shù)中有yield,所以它變成了一個(gè)迭代器,可以用于迭代。
執(zhí)行第一次迭代時(shí)(其實(shí)就是調(diào)用next()方法),如果有左節(jié)點(diǎn)并且距離滿足要求,會(huì)執(zhí)行第一個(gè)yield,這時(shí)會(huì)返回self._leftchild并完成第一個(gè)迭代。
執(zhí)行第二次迭代時(shí),從第一個(gè)yield后面開始,如果有右節(jié)點(diǎn)并且距離滿足要求,會(huì)執(zhí)行第二個(gè)yield,這時(shí)會(huì)返回self._rightchild并完成第一個(gè)迭代。
執(zhí)行第三次迭代時(shí),第二個(gè)yield后再無代碼,捕獲異常,退出迭代。
調(diào)用過程:
result, candidates = list(), [self] while candidates: node = candidates.pop() distance = node._get_dist(obj) if distance <= max_dist and distance >= min_dist: result.extend(node._values) candidates.extend(node._get_child_candidates(distance, min_dist, max_dist)) return result
上面的node._get_child_candidates(self, distance, min_dist, max_dist)
是放在extend()函數(shù)中作為參數(shù)的,為什么可以這么用,就因?yàn)閑xtend函數(shù)的參數(shù)不僅僅支持array,只要它是一個(gè)迭代器就可以。它的原型是array.extend(iterable)。
代碼示例3:
總結(jié)
以上就是這篇文章的全部?jī)?nèi)容了,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,謝謝大家對(duì)腳本之家的支持。如果你想了解更多相關(guān)內(nèi)容請(qǐng)查看下面相關(guān)鏈接
相關(guān)文章
在Python中使用K-Means聚類和PCA主成分分析進(jìn)行圖像壓縮
這篇文章主要介紹了在Python中使用K-Means聚類和PCA主成分分析進(jìn)行圖像壓縮,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-04-04Python進(jìn)階多線程爬取網(wǎng)頁項(xiàng)目實(shí)戰(zhàn)
這篇文章主要為大家介紹了Python進(jìn)階,Python多線程爬取網(wǎng)頁項(xiàng)目實(shí)戰(zhàn)的示例呈現(xiàn)步驟,有需要的朋友可以借鑒參考下,希望能夠有所幫助2021-10-10在django中form的label和verbose name的區(qū)別說明
這篇文章主要介紹了在django中form的label和verbose name的區(qū)別說明,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2020-05-05Python高級(jí)過濾器之filter函數(shù)詳解
在Python中,filter()是一個(gè)非常有用的內(nèi)置函數(shù),它能夠根據(jù)指定的函數(shù)來篩選出可迭代對(duì)象中滿足條件的元素,本文將從入門到精通,全面介紹filter()函數(shù)的用法和相關(guān)知識(shí)點(diǎn)2023-08-08Python利用pandas和matplotlib實(shí)現(xiàn)繪制堆疊柱狀圖
在數(shù)據(jù)可視化中,堆疊柱狀圖是一種常用的圖表類型,它能夠清晰地展示多個(gè)類別的數(shù)據(jù),本文將演示如何使用 Python 的 pandas 和 matplotlib 庫繪制優(yōu)化的堆疊柱狀圖,需要的可以參考下2023-11-11基于Python實(shí)現(xiàn)視頻分辨率轉(zhuǎn)換
這篇文章主要介紹了基于Python實(shí)現(xiàn)視頻的分辨率轉(zhuǎn)換的示例代碼,文中的代碼講解詳細(xì),對(duì)學(xué)習(xí)Python有一定的幫助,感興趣的小伙伴可以了解一下2021-12-122款Python內(nèi)存檢測(cè)工具介紹和使用方法
這篇文章主要介紹了2款Python內(nèi)存檢測(cè)工具介紹和使用方法,可以用來分析Python程序的內(nèi)存使用量,需要的朋友可以參考下2014-06-06Python遞歸遍歷列表及輸出的實(shí)現(xiàn)方法
這篇文章主要介紹了Python遞歸遍歷列表及輸出的實(shí)現(xiàn)方法,可實(shí)現(xiàn)遞歸遍歷列表中的每一項(xiàng),若是元祖則判斷是否為基本類型然后輸出,需要的朋友可以參考下2015-05-05