Python11月28日
生成器
通過列表生成式,我們可以直接建立一個列表。但是,受到記憶體限制,列表容量肯定是有限的。而且,建立一個包含100萬個元素的列表,不僅佔用很大的儲存空間,如果我們僅僅需要訪問前面幾個元素,那後面絕大多數元素佔用的空間都白白浪費了。
所以,如果列表元素可以按照某種演算法推算出來,那我們是否可以在迴圈的過程中不斷推算出後續的元素呢?這樣就不必建立完整的list,從而節省大量的空間。在Python中,這種一邊迴圈一邊計算的機制,稱為生成器:generator。
要建立一個generator,有很多種方法。第一種方法很簡單,只要把一個列表生成式的[]
改成()
,就建立了一個generator:
>>> L = [x * x for x in range(10)] >>> L [0, 1, 4, 9, 16, 25, 36, 49, 64, 81] >>> g = (x * x for x in range(10)) >>> g <generator object <genexpr> at 0x1022ef630>
建立L
和g
的區別僅在於最外層的[]
和()
,L
是一個list,而g
是一個generator。
我們怎麼打印出generator的每一個元素呢?
第一個是用next()來實現,但是這個方法太變態了
所以我們使用第二種方法:使用for
迴圈,因為generator也是可迭代物件
# g=(x * x for x in range(1,11))
# for i in g:
# print(i)
迭代器
可以直接作用於for
迴圈的資料型別有以下幾種:
一類是集合資料型別,如list
、tuple
、dict
、set
、str
等;
一類是generator
,包括生成器和帶yield
的generator function。
這些可以直接作用於for
迴圈的物件統稱為可迭代物件:Iterable
可以使用isinstance()
判斷一個物件是否是Iterable
物件:
from collections.abc import Iterable
>>> isinstance([], Iterable)
True
可以被next()
函式呼叫並不斷返回下一個值的物件稱為迭代器:Iterator
。
可以使用isinstance()
判斷一個物件是否是Iterator
物件:
>>> from collections.abc import Iterator
>>> isinstance((x for x in range(10)), Iterator)
True
生成器都是Iterator
物件,但list
、dict
、str
雖然是Iterable
,卻不是Iterator
。
把list
、dict
、str
等Iterable
變成Iterator
可以使用iter()
函式:
>>> isinstance(iter([]), Iterator) True >>> isinstance(iter('abc'), Iterator) True
凡是可作用於for
迴圈的物件都是Iterable
型別;
凡是可作用於next()
函式的物件都是Iterator
型別,它們表示一個惰性計算的序列;
集合資料型別如list
、dict
、str
等是Iterable
但不是Iterator
,不過可以通過iter()
函式獲得一個Iterator
物件