Python小知識點——生成器(generator)與關鍵字yield的運用

生成器(generator)是一種可迭代對象。

在處理包含大量數據時,如果使用list來進行操作,會導致內存佔用大,效率低。生成器通過延遲計算,實現了一種邊循環邊計算的可能,只有在需要的時候才返回相應的結果,而不是一次性返回一整個結果列表,因此可以有效地節省了大量的空間。

首先,根據列表生成式,將[]改成()即可創建一個generator

>>> a = (x * x for x in [1,2,3])  # 列表生成式:a = [x * x for x in [1,2,3]]

# 如果你想轉成list類型,可以直接用list(a)。

輸出元素,可以使用next()

>>> next(a)
1
>>> next(a)
4
>>> next(a)
9

每一次調用next(a),a就會接着上一次的循環輸出下一次的結果。當循環完全部元素後,再調用next(a),就會報錯。

另外,因爲生成器本身是可迭代對象,所以你也可以使用for in 循環遍歷直接輸出結果。

>>> for x in a:
	print(x)	
1
4
9

對生成器有了初步認識後,我們就可以開始掌握關鍵字yield了。

其實很簡單,關鍵字yield的作用就是替代關鍵字return,如果一個函數中使用了yield來返回結果,我們就認爲這個函數是一個生成器

def func(n):
    for i in range(1,n):
        result = i * i
        yield result

# 將(x * x for x in [1,2,3])用函數的方式表示

瞭解生成器(generator)與關鍵字yield的知識後

我們將上面的代碼擴展一下

def func(n):
    for i in range(1,n):
        result = i * i
        yield result

func = func(5)
for x in func:
    print(x)
for x in func:
    print(x)

運行結果:

>>> 
1
4
9
16

結果可知,本應該輸出了兩次循環的結果,卻只輸出了一次循環。如果你在兩個循環中間,添加一個print(list(func))語句,你就會發現由generator轉換成list的func是空的,即func=[],func內部的元素似乎被“清空”了。

注意:一個生成器只能遍歷一次。

爲什麼會這樣呢?其實在調用next()方法的時候就大概明白了,每一次調用next()的時候,循環處於“工作”狀態,不調用的時候,程序就處於一種“暫停”的狀態,直到再次被調用,纔會“工作”。當循環到最後一個元素後,我們再調用next()時就會報錯。這說明了生成器只是代表了一次完整的循環中不斷計算結果的過程。

那如果你還是希望能讓你的生成器能被多次調用的話,你可以這樣做

1、將生成器轉換成list,再進行遍歷

func = list(func(5))

2、需要遍歷幾次,就生成多少個可迭代對象(generator),再分別遍歷

func1 = list(func(5))
func2 = list(func(5))
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章