一、說明
return一直中,每中語言中其沒沒有很大差別,就不多說了,(shell語言return的是退出狀態,可能差別是比較大的)
最早看到yield應該是哪們語言用來調整什么執行緒優先級的,記不清了,不過那里的yield和python中的yield應該功能有區別,
python中最早看到yield應該是使用scrapy框架寫爬蟲的時候,之前也有去看yiled的用法,總記不太住,今天又去看了一下,基本上來就是講些斐波那契數列的煩的要死,自己寫段程式研究了一下,這里記一下,
二、return和yield的異同
共同點:return和yield都用來回傳值;在一次性地回傳所有值場景中return和yield的作用是一樣的,
不同點:如果要回傳的資料是通過for等回圈生成的迭代器型別資料(如串列、元組),return只能在回圈外部一次性地回傳,yeild則可以在回圈內部逐個元素回傳,下邊我們舉例說明這個不同點,
三、實體說明
1 return版本
示例代碼如下:
class TestYield:
def gen_iterator(self):
result_list = []
for j in range(3):
print(f"gen_iterator-{j}")
result_list.append(j)
# return在回圈的外部,待變數完全生成后一次性回傳
return result_list
def call_gen_iterator(self):
# 執行下邊這句后result_list直接是完成的結果[0,1,2]
result_list = self.gen_iterator()
for i in result_list:
print(f"call_gen_iterator-{i}")
if __name__ == "__main__":
obj = TestYield()
obj.call_gen_iterator()
執行結果如下,可以看到一次性執行完下層函式,生成完整的迭代器型別回傳值result_list,一次性回傳給上層函式:

2 yield版本
示例代碼如下:
'''
學習中遇到問題沒人解答?小編創建了一個Python學習交流群:857662006
尋找有志同道合的小伙伴,互幫互助,群里還有不錯的視頻學習教程和PDF電子書!
'''
class TestYield:
def gen_iterator(self):
for j in range(3):
print(f"do_something-{j}")
# yield在for回圈內部
yield j
def call_gen_iterator(self):
# yield并不是直接回傳[0,1,2],執行下邊這句后result_list什么值都沒有
result_list = self.gen_iterator()
# i每請求一個資料,才會觸發gen_iterator生成一個資料
for i in result_list:
print(f"call_gen_iterator-{i}")
if __name__ == "__main__":
obj = TestYield()
obj.call_gen_iterator()
執行結果如下,可以看到上下層函式是交替進行的,即上層函式請求迭代一個值下層函式才生成一個值并立即回傳這個值:

3 yield的意義
從上邊兩個小節可以看到,雖然return和yield兩者執行的順序有區別,但整個要做的事情是一樣的,所以使用yield并不會比return快,甚至我們可以猜測由于yield總發生背景關系切換在速度上還會慢一些,所以速度不是yield的意義,
他們的主要區別是yiled要迭代到哪個元素那個元素才即時地生成,而return要用一個中間變數result_list保存回傳值,當result_list的長度很長且每個組成元素內容很大時將會耗費比較大的記憶體,此時yield相對return才有優勢,
四、yield和return嵌套使用
class TestYield:
def gen_iterator(self):
for j in range(3):
print(f"do_something-{j}")
# yield在for回圈內部
yield j
def gen_iterator_middle(self):
print(f"gen_iterator_middle")
# 回傳的是迭代器的句柄,所以加一層return不影響是可以理解的
return self.gen_iterator()
def call_gen_iterator(self):
# yield并不是直接回傳[0,1,2],執行下邊這句后result_list什么值都沒有
result_list = self.gen_iterator_middle()
# i每請求一個資料,才會觸發gen_iterator生成一個資料
for i in result_list:
print(f"call_gen_iterator-{i}")
if __name__ == "__main__":
obj = TestYield()
obj.call_gen_iterator()

轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/486596.html
標籤:Python
