首先,如果你還沒(méi)有對(duì)yield有個(gè)初步分認(rèn)識(shí)畅铭,那么你先把yield看做“return”菠隆,這個(gè)是直觀的兵琳,它首先是個(gè)return,普通的return是什么意思骇径,就是在程序中返回某個(gè)值躯肌,返回之后程序就不再往下運(yùn)行了∑葡危看做return之后再把它看做一個(gè)是生成器(generator)的一部分(帶yield的函數(shù)才是真正的迭代器)羡榴,好了,如果你對(duì)這些不明白的話运敢,那先把yield看做return,然后直接看下面的程序校仑,你就會(huì)明白yield的全部意思了:
def foo():
print("starting...")
while True:
res = yield 4
print("res:",res)
g = foo()
print(next(g))
print("*"*20)
print(next(g))
運(yùn)行結(jié)果:
starting...
4
********************
res: None
4
1.程序開(kāi)始執(zhí)行以后,因?yàn)閒oo函數(shù)中有yield關(guān)鍵字传惠,所以foo函數(shù)并不會(huì)真的執(zhí)行迄沫,而是先得到一個(gè)生成器g(相當(dāng)于一個(gè)對(duì)象)
2.直到調(diào)用next方法,foo函數(shù)正式開(kāi)始執(zhí)行卦方,先執(zhí)行foo函數(shù)中的print方法羊瘩,然后進(jìn)入while循環(huán)
3.程序遇到y(tǒng)ield關(guān)鍵字,然后把yield想想成return,return了一個(gè)4之后盼砍,程序停止尘吗,并沒(méi)有執(zhí)行賦值給res操作,此時(shí)next(g)語(yǔ)句執(zhí)行完成浇坐,所以輸出的前兩行(第一個(gè)是while上面的print的結(jié)果,第二個(gè)是return出的結(jié)果)是執(zhí)行print(next(g))的結(jié)果睬捶,
4.程序執(zhí)行print(""20),輸出20個(gè)*
5.又開(kāi)始執(zhí)行下面的print(next(g)),這個(gè)時(shí)候和上面那個(gè)差不多近刘,不過(guò)不同的是擒贸,這個(gè)時(shí)候是從剛才那個(gè)next程序停止的地方開(kāi)始執(zhí)行的,也就是要執(zhí)行res的賦值操作觉渴,這時(shí)候要注意介劫,這個(gè)時(shí)候賦值操作的右邊是沒(méi)有值的(因?yàn)閯偛拍莻€(gè)是return出去了,并沒(méi)有給賦值操作的左邊傳參數(shù))案淋,所以這個(gè)時(shí)候res賦值是None,所以接著下面的輸出就是res:None,
6.程序會(huì)繼續(xù)在while里執(zhí)行座韵,又一次碰到y(tǒng)ield,這個(gè)時(shí)候同樣return 出4,然后程序停止踢京,print函數(shù)輸出的4就是這次return出的4.
到這里你可能就明白yield和return的關(guān)系和區(qū)別了誉碴,帶yield的函數(shù)是一個(gè)生成器宦棺,而不是一個(gè)函數(shù)了,這個(gè)生成器有一個(gè)函數(shù)就是next函數(shù)翔烁,next就相當(dāng)于“下一步”生成哪個(gè)數(shù),這一次的next開(kāi)始的地方是接著上一次的next停止的地方執(zhí)行的旨涝,所以調(diào)用next的時(shí)候蹬屹,生成器并不會(huì)從foo函數(shù)的開(kāi)始執(zhí)行,只是接著上一步停止的地方開(kāi)始白华,然后遇到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))
再看一個(gè)這個(gè)生成器的send函數(shù)的例子厦取,這個(gè)例子就把上面那個(gè)例子的最后一行換掉了,輸出結(jié)果:
starting...
4
********************
res: 7
4
先大致說(shuō)一下send函數(shù)的概念:此時(shí)你應(yīng)該注意到上面那個(gè)的紫色的字管搪,還有上面那個(gè)res的值為什么是None虾攻,這個(gè)變成了7,到底為什么更鲁,這是因?yàn)轹浚瑂end是發(fā)送一個(gè)參數(shù)給res的,因?yàn)樯厦嬷v到澡为,return的時(shí)候漂坏,并沒(méi)有把4賦值給res,下次執(zhí)行的時(shí)候只好繼續(xù)執(zhí)行賦值操作媒至,只好賦值為None了顶别,而如果用send的話,開(kāi)始執(zhí)行的時(shí)候拒啰,先接著上一次(return 4之后)執(zhí)行驯绎,先把7賦值給了res,然后執(zhí)行next的作用,遇見(jiàn)下一回的yield谋旦,return出結(jié)果后結(jié)束条篷。
5.程序執(zhí)行g(shù).send(7),程序會(huì)從yield關(guān)鍵字那一行繼續(xù)向下運(yùn)行蛤织,send會(huì)把7這個(gè)值賦值給res變量
6.由于send方法中包含next()方法赴叹,所以程序會(huì)繼續(xù)向下運(yùn)行執(zhí)行print方法,然后再次進(jìn)入while循環(huán)
7.程序執(zhí)行再次遇到y(tǒng)ield關(guān)鍵字指蚜,yield會(huì)返回后面的值后乞巧,程序再次暫停,直到再次調(diào)用next方法或send方法摊鸡。