def add(n,i): return n+i def test(): for i in range(4): yield i g=test() for n in [1,10]: g=(add(n,i) for i in g) print(n) print(list(g))
10 [20, 21, 22, 23]
第一個函數add就是實現了一個簡單的加法運算 第二個函數test是一個生成器函數,若是調用它會返回一個生成器 g=test(),這一行調用了生成器函數,因此此刻g就是一個生成器(它的本質仍是迭代器) 而後執行for循環,這裏迷惑人的就是這個for循環,爲了減小它的魔性,咱們把for循環拆開來看: 當n = 1時: 執行了:g=(add(n,i) for i in g) 當n = 10時: 執行了:g=(add(n,i) for i in g)
乍一看這兩行代碼仍是有點迷糊,可是咱們要知道,生成器有個最大的特性就是惰性,當你不進行迭代時它就不進行運算,想要對生成器進行迭代有如下幾種方法:
第一種:for循環,for循環的本質就是調用了iter和next方法進行了迭代
第二種:調用next方法
第三種:調用send方法
第四種:數據類型強制轉換,好比使用list()強制轉換。
只要沒有以上四種方法進行迭代,那麼生成器就沒有進行運算,因此在上面的for循環中不管是n=1時仍是n=10時,生成器 g 都沒有參與運算,python
當n = 1時,g=(add(n,i) for i in g),這個表達式的結果g 就是一個表達式,沒有進行運算,g的值就是一個表達式(add(n,i) for i in g),括號裏面的g其實是test(),因此g = (add(n,i) for i in test()),僅此而已
當n = 10時,g=(add(n,i) for i in g),把n=1時的g的結果帶入進去就是g=(add(n,i) for i in (add(n,i) for i in test()))面試
當整段代碼執行到print(list(g))語句以前,g的值就是一段代碼,或者你能夠稱之爲算法,沒有進行任何運算,裏面的n就是n,g就是g
不過此時由於代碼是按照流程執行的,而且for循環已經執行完畢,因此n的值等於10算法
當執行print(list(g))語句時,生成器纔開始輸出數據,此時執行最後一個g的賦值語句:
g=(add(n,i) for i in (add(n,i) for i in test()))
這時 n 的值等於10(由於代碼是按照流程執行的,for循環已經執行完了,n的最終結果就是10),其中後面的(add(n,i) for i in test())這段代碼的結果依然是個生成器,迭代後應爲[10,11,12,13],因此最終的結果能夠理解成:(add(n,i) for i in [10,11,12,13]),因此最終結果爲:20,21,22,23函數