Python教程:return和yield的區別

python学习者0發表於2024-04-13

return一直中,每中語言中其沒沒有很大差別,就不多說了。(shell語言return的是退出狀態,可能差別是比較大的)

最早看到yield應該是哪們語言用來調整什麼執行緒優先順序的,記不清了,不過那裡的yield和python中的yield應該功能有區別。

一、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版本

示例程式碼如下:

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):
	    #學習中遇到問題沒人解答?小編建立了一個Python學習交流群:153708845
        # 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()

在這裡插入圖片描述

相關文章