python中yield的用法詳解——最簡單,最清晰的解釋

原文地址:https://blog.csdn.net/mieleizhi0522/article/details/82142856

首先我要吐槽一下,看程序的過程中遇見了yield這個關(guān)鍵字,然后百度的時候,發(fā)現(xiàn)沒有一個能簡單的讓我懂的槽片,講起來真TM的都是頭頭是道何缓,什么參數(shù),什么傳遞的还栓,還口口聲聲說自己的教程是最簡單的碌廓,最淺顯易懂的,我就想問沒有有考慮過讀者的感受剩盒。

接下來是正題:

首先谷婆,如果你還沒有對yield有個初步分認識,那么你先把yield看做“return”辽聊,這個是直觀的纪挎,它首先是個return,普通的return是什么意思跟匆,就是在程序中返回某個值异袄,返回之后程序就不再往下運行了÷瓯郏看做return之后再把它看做一個是生成器(generator)的一部分(帶yield的函數(shù)才是真正的迭代器)烤蜕,好了,如果你對這些不明白的話迹冤,那先把yield看做return,然后直接看下面的程序讽营,你就會明白yield的全部意思了:

def foo():
    print("starting...")
    while True:
        res = yield 4
        print("res:",res)
g = foo()
print(next(g))
print("*"*20)
print(next(g))

就這么簡單的幾行代碼就讓你明白什么是yield,代碼的輸出這個:

starting...
4
********************
res: None
4

我直接解釋代碼運行順序泡徙,相當于代碼單步調(diào)試:

1.程序開始執(zhí)行以后橱鹏,因為foo函數(shù)中有yield關(guān)鍵字,所以foo函數(shù)并不會真的執(zhí)行堪藐,而是先得到一個生成器g(相當于一個對象)

2.直到調(diào)用next方法蚀瘸,foo函數(shù)正式開始執(zhí)行,先執(zhí)行foo函數(shù)中的print方法庶橱,然后進入while循環(huán)

3.程序遇到y(tǒng)ield關(guān)鍵字贮勃,然后把yield想想成return,return了一個4之后,程序停止苏章,并沒有執(zhí)行賦值給res操作寂嘉,此時next(g)語句執(zhí)行完成奏瞬,所以輸出的前兩行(第一個是while上面的print的結(jié)果,第二個是return出的結(jié)果)是執(zhí)行print(next(g))的結(jié)果,

4.程序執(zhí)行print(""20)泉孩,輸出20個*

5.又開始執(zhí)行下面的print(next(g)),這個時候和上面那個差不多硼端,不過不同的是,這個時候是從剛才那個next程序停止的地方開始執(zhí)行的寓搬,也就是要執(zhí)行res的賦值操作珍昨,這時候要注意,這個時候賦值操作的右邊是沒有值的(因為剛才那個是return出去了句喷,并沒有給賦值操作的左邊傳參數(shù))镣典,所以這個時候res賦值是None,所以接著下面的輸出就是res:None,

6.程序會繼續(xù)在while里執(zhí)行,又一次碰到y(tǒng)ield,這個時候同樣return 出4唾琼,然后程序停止兄春,print函數(shù)輸出的4就是這次return出的4.

到這里你可能就明白yield和return的關(guān)系和區(qū)別了,帶yield的函數(shù)是一個生成器锡溯,而不是一個函數(shù)了赶舆,這個生成器有一個函數(shù)就是next函數(shù),next就相當于“下一步”生成哪個數(shù)祭饭,這一次的next開始的地方是接著上一次的next停止的地方執(zhí)行的芜茵,所以調(diào)用next的時候,生成器并不會從foo函數(shù)的開始執(zhí)行倡蝙,只是接著上一步停止的地方開始夕晓,然后遇到y(tǒng)ield后,return出要生成的數(shù)悠咱,此步就結(jié)束蒸辆。


def foo():
    print("starting...")
    while True:
        res = yield 4
        print("res:",res)
g = foo()
print(next(g))
print("*"*20)
print(g.send(7))

再看一個這個生成器的send函數(shù)的例子,這個例子就把上面那個例子的最后一行換掉了析既,輸出結(jié)果:

starting...
4
********************
res: 7
4

先大致說一下send函數(shù)的概念:此時你應(yīng)該注意到上面那個的紫色的字躬贡,還有上面那個res的值為什么是None,這個變成了7眼坏,到底為什么拂玻,這是因為,send是發(fā)送一個參數(shù)給res的宰译,因為上面講到檐蚜,return的時候,并沒有把4賦值給res沿侈,下次執(zhí)行的時候只好繼續(xù)執(zhí)行賦值操作闯第,只好賦值為None了,而如果用send的話缀拭,開始執(zhí)行的時候咳短,先接著上一次(return 4之后)執(zhí)行填帽,先把7賦值給了res,然后執(zhí)行next的作用,遇見下一回的yield咙好,return出結(jié)果后結(jié)束篡腌。

5.程序執(zhí)行g(shù).send(7),程序會從yield關(guān)鍵字那一行繼續(xù)向下運行勾效,send會把7這個值賦值給res變量

6.由于send方法中包含next()方法嘹悼,所以程序會繼續(xù)向下運行執(zhí)行print方法,然后再次進入while循環(huán)

7.程序執(zhí)行再次遇到y(tǒng)ield關(guān)鍵字层宫,yield會返回后面的值后杨伙,程序再次暫停,直到再次調(diào)用next方法或send方法卒密。

這就結(jié)束了,說一下棠赛,為什么用這個生成器哮奇,是因為如果用List的話,會占用更大的空間睛约,比如說取0,1,2,3,4,5,6............1000

你可能會這樣:

for n in range(1000):
    a=n

這個時候range(1000)就默認生成一個含有1000個數(shù)的list了鼎俘,所以很占內(nèi)存。

這個時候你可以用剛才的yield組合成生成器進行實現(xiàn)辩涝,也可以用xrange(1000)這個生成器實現(xiàn)

yield組合:

def foo(num):
    print("starting...")
    while num<10:
        num=num+1
        yield num
for n in foo(0):
    print(n)

輸出:

starting...
1
2
3
4
5
6
7
8
9
10

xrange(1000):

for n in xrange(1000):
    a=n

其中要注意的是python3時已經(jīng)沒有xrange()了贸伐,在python3中,range()就是xrange()了怔揩,你可以在python3中查看range()的類型捉邢,它已經(jīng)是個<class 'range'>了,而不是一個list了商膊,畢竟這個是需要優(yōu)化的伏伐。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市晕拆,隨后出現(xiàn)的幾起案子藐翎,更是在濱河造成了極大的恐慌,老刑警劉巖实幕,帶你破解...
    沈念sama閱讀 212,816評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件吝镣,死亡現(xiàn)場離奇詭異,居然都是意外死亡昆庇,警方通過查閱死者的電腦和手機末贾,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,729評論 3 385
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來整吆,“玉大人未舟,你說我怎么就攤上這事圈暗。” “怎么了裕膀?”我有些...
    開封第一講書人閱讀 158,300評論 0 348
  • 文/不壞的土叔 我叫張陵员串,是天一觀的道長。 經(jīng)常有香客問我昼扛,道長寸齐,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,780評論 1 285
  • 正文 為了忘掉前任抄谐,我火速辦了婚禮渺鹦,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘蛹含。我一直安慰自己毅厚,他們只是感情好,可當我...
    茶點故事閱讀 65,890評論 6 385
  • 文/花漫 我一把揭開白布浦箱。 她就那樣靜靜地躺著吸耿,像睡著了一般。 火紅的嫁衣襯著肌膚如雪酷窥。 梳的紋絲不亂的頭發(fā)上咽安,一...
    開封第一講書人閱讀 50,084評論 1 291
  • 那天,我揣著相機與錄音蓬推,去河邊找鬼妆棒。 笑死,一個胖子當著我的面吹牛沸伏,可吹牛的內(nèi)容都是我干的糕珊。 我是一名探鬼主播,決...
    沈念sama閱讀 39,151評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼毅糟,長吁一口氣:“原來是場噩夢啊……” “哼放接!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起留特,我...
    開封第一講書人閱讀 37,912評論 0 268
  • 序言:老撾萬榮一對情侶失蹤纠脾,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后蜕青,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體苟蹈,經(jīng)...
    沈念sama閱讀 44,355評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,666評論 2 327
  • 正文 我和宋清朗相戀三年右核,在試婚紗的時候發(fā)現(xiàn)自己被綠了慧脱。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,809評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡贺喝,死狀恐怖菱鸥,靈堂內(nèi)的尸體忽然破棺而出宗兼,到底是詐尸還是另有隱情,我是刑警寧澤氮采,帶...
    沈念sama閱讀 34,504評論 4 334
  • 正文 年R本政府宣布殷绍,位于F島的核電站,受9級特大地震影響鹊漠,放射性物質(zhì)發(fā)生泄漏主到。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 40,150評論 3 317
  • 文/蒙蒙 一躯概、第九天 我趴在偏房一處隱蔽的房頂上張望登钥。 院中可真熱鬧,春花似錦娶靡、人聲如沸牧牢。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,882評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽塔鳍。三九已至,卻和暖如春艾凯,著一層夾襖步出監(jiān)牢的瞬間献幔,已是汗流浹背懂傀。 一陣腳步聲響...
    開封第一講書人閱讀 32,121評論 1 267
  • 我被黑心中介騙來泰國打工趾诗, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人蹬蚁。 一個月前我還...
    沈念sama閱讀 46,628評論 2 362
  • 正文 我出身青樓恃泪,卻偏偏與公主長得像,于是被迫代替她去往敵國和親犀斋。 傳聞我的和親對象是個殘疾皇子贝乎,可洞房花燭夜當晚...
    茶點故事閱讀 43,724評論 2 351

推薦閱讀更多精彩內(nèi)容