生成器generator
盡管列表解析可以方便地創(chuàng)建列表叽讳,但會(huì)占用內(nèi)存追他,而且容量有限(受內(nèi)存影響)。如果列表元素可以按照某種算法推算出來岛蚤,那我們就可以創(chuàng)建生成器generator
邑狸,這樣就不必創(chuàng)建完整的list。生成的generator
可以理解為iterator
涤妒,用for
循環(huán)來迭代它单雾。如果推算的算法比較復(fù)雜,用類似for
循環(huán)無法實(shí)現(xiàn)她紫,可以用定義函數(shù)來實(shí)現(xiàn)硅堆。根本上來說,迭代器就是一個(gè)有nest()
方法的對象贿讹。條目全部取出后渐逃,會(huì)引發(fā)一個(gè) StopIteration 異常。生成器表達(dá)式就好像是惰性的列表解析民褂。
語法:
(expression for iter_val in iterator)
#語法與列表解析一樣茄菊,只需把`[]`改成`()`。
例如計(jì)算文本文件中非空字符總和赊堪,如果用列表解析面殖,內(nèi)存性能會(huì)很低,用生成器表達(dá)式會(huì)很方便實(shí)惠:
sum(len(word) for line in date for word in line.split())
另一種創(chuàng)建生成器的方法:定義一個(gè)函數(shù)哭廉,采用yield
語句:
aa='def'
def bb():
yield 'a'
yield 'b'
yield 'c'
aa_product_bb=[x+y for x in aa for y in bb()]
# return ['da','db','dc','ea','eb','ec','fa','fb','fc']
這里在列表解析中脊僚,兩個(gè)for
循環(huán),有一個(gè)是生成器bb()
,另一個(gè)是可迭代對象遵绰。如果兩個(gè)都是迭代器辽幌,就會(huì)出問題增淹!具體的原因未知...
利用yield
語句定義fibonaci數(shù)列:
def fib(max):
n,a,b=0,0,1
while n<max:
yiled b
a,b=,b,a+b
n+=1
return 'done'
函數(shù)定義中包含yield
關(guān)鍵字,這個(gè)函數(shù)就不是一個(gè)普通的函數(shù)舶衬,而是一個(gè)generator
埠通。
迭代器
可以直接用for
循環(huán)作用的數(shù)據(jù)類型有:
- 集合數(shù)據(jù)類型:
list
,tuple
,dict
,set
,str
. - generator: 生成器及帶
yield
的generator function.
這些可以直接用for
循環(huán)作用的對象統(tǒng)稱為可迭代對象Iterable
赎离」溆蹋可以用isinstance()
判斷對象是否為Iterable
對象:
isinstance((x for x in range(10)),Iterable) #return True
可以被next()
函數(shù)調(diào)用并不斷返回下一個(gè)值的對象稱為迭代器:Iterator
.
生成器都是Iterator
對象,但list
,dict
,str
雖然是Iterable
,卻不是Iterator
,可以利用函數(shù)iter()
使它們變成Iterator
.
Iterator
可以表示一個(gè)無限大的數(shù)據(jù)流梁剔,且不會(huì)占用大內(nèi)存虽画。for
循環(huán)本質(zhì)上不斷調(diào)用next(0
函數(shù)實(shí)現(xiàn)的。
[廖雪峰網(wǎng)站](http://www.liaoxuefeng.com