生成器generator
盡管列表解析可以方便地創建列表,但會占用內存,而且容量有限(受內存影響)。如果列表元素可以按照某種算法推算出來,那我們就可以創建生成器generator
,這樣就不必創建完整的list。生成的generator
可以理解為iterator
,用for
循環來迭代它。如果推算的算法比較復雜,用類似for
循環無法實現,可以用定義函數來實現。根本上來說,迭代器就是一個有nest()
方法的對象。條目全部取出后,會引發一個 StopIteration 異常。生成器表達式就好像是惰性的列表解析。
語法:
(expression for iter_val in iterator)
#語法與列表解析一樣,只需把`[]`改成`()`。
例如計算文本文件中非空字符總和,如果用列表解析,內存性能會很低,用生成器表達式會很方便實惠:
sum(len(word) for line in date for word in line.split())
另一種創建生成器的方法:定義一個函數,采用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']
這里在列表解析中,兩個for
循環,有一個是生成器bb()
,另一個是可迭代對象。如果兩個都是迭代器,就會出問題!具體的原因未知...
利用yield
語句定義fibonaci數列:
def fib(max):
n,a,b=0,0,1
while n<max:
yiled b
a,b=,b,a+b
n+=1
return 'done'
函數定義中包含yield
關鍵字,這個函數就不是一個普通的函數,而是一個generator
。
迭代器
可以直接用for
循環作用的數據類型有:
- 集合數據類型:
list
,tuple
,dict
,set
,str
. - generator: 生成器及帶
yield
的generator function.
這些可以直接用for
循環作用的對象統稱為可迭代對象Iterable
。可以用isinstance()
判斷對象是否為Iterable
對象:
isinstance((x for x in range(10)),Iterable) #return True
可以被next()
函數調用并不斷返回下一個值的對象稱為迭代器:Iterator
.
生成器都是Iterator
對象,但list
,dict
,str
雖然是Iterable
,卻不是Iterator
,可以利用函數iter()
使它們變成Iterator
.
Iterator
可以表示一個無限大的數據流,且不會占用大內存。for
循環本質上不斷調用next(0
函數實現的。
[廖雪峰網站](http://www.liaoxuefeng.com