生成器
只要把一個(gè)列表生成式的[]改成()殖侵,就創(chuàng)建了一個(gè)generator,生成器的意義在于一邊循環(huán)一遍計(jì)算的機(jī)制,節(jié)省大量的內(nèi)存空間和屎,generator保存的是算法,調(diào)用next方法計(jì)算下一個(gè)元素的值春瞬,直到最后拋出StopIteration異常
>>> 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>
>>> next(g)
0
>>> next(g)
1
生成器是支持for循環(huán)的可迭代對(duì)象
>>> g = (x * x for x in range(10))
>>> for n in g:
... print(n)
如果一個(gè)函數(shù)定義中包含yield關(guān)鍵字柴信,那么這個(gè)函數(shù)就不再是一個(gè)普通函數(shù),而是一個(gè)generator
def fib(max):
n, a, b = 0, 0, 1
while n < max:
yield b
a, b = b, a + b
n = n + 1
return 'done'
>>> f = fib(6)
>>> f
<generator object fib at 0x104feaaa0>
generator和函數(shù)的執(zhí)行流程不一樣宽气。函數(shù)是順序執(zhí)行随常,遇到return語(yǔ)句或者最后一行函數(shù)語(yǔ)句就返回。而變成generator的函數(shù)萄涯,在每次調(diào)用next()的時(shí)候執(zhí)行绪氛,遇到y(tǒng)ield語(yǔ)句返回,再次執(zhí)行時(shí)從上次返回的yield語(yǔ)句處繼續(xù)執(zhí)行
def odd():
print('step 1')
yield 1
print('step 2')
yield(3)
print('step 3')
yield(5)
>>> o = odd()
>>> next(o)
step 1
1
>>> next(o)
step 2
3
>>> next(o)
step 3
5
>>> next(o)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
StopIteration
把函數(shù)改成generator后涝影,也成為支持for循環(huán)遍歷的對(duì)象
迭代器
可以直接作用于for循環(huán)的數(shù)據(jù)類型有以下幾種:
一類是集合數(shù)據(jù)類型枣察,如list、tuple燃逻、dict询件、set、str等唆樊;
一類是generator宛琅,包括生成器和帶yield的generator function。
這些可以直接作用于for循環(huán)的對(duì)象統(tǒng)稱為可迭代對(duì)象:Iterable逗旁『俦伲可以使用isinstance()判斷一個(gè)對(duì)象是否是Iterable對(duì)象
>>> from collections import Iterable
>>> isinstance([], Iterable)
True
>>> isinstance({}, Iterable)
True
>>> isinstance('abc', Iterable)
True
>>> isinstance((x for x in range(10)), Iterable)
True
>>> isinstance(100, Iterable)
False
可以被next()函數(shù)調(diào)用并不斷返回下一個(gè)值的對(duì)象稱為迭代器:Iterator∑В可以使用isinstance()判斷一個(gè)對(duì)象是否是Iterator對(duì)象:
>>> from collections import Iterator
>>> isinstance((x for x in range(10)), Iterator)
True
>>> isinstance([], Iterator)
False
>>> isinstance({}, Iterator)
False
>>> isinstance('abc', Iterator)
False
生成器都是Iterator對(duì)象红伦,但list、dict淀衣、str雖然是Iterable昙读,卻不是Iterator。把list膨桥、dict蛮浑、str等Iterable變成Iterator可以使用iter()函數(shù):
>>> isinstance(iter([]), Iterator)
True
>>> isinstance(iter('abc'), Iterator)
True
Python的Iterator對(duì)象表示的是一個(gè)數(shù)據(jù)流唠叛,Iterator對(duì)象可以被next()函數(shù)調(diào)用并不斷返回下一個(gè)數(shù)據(jù),直到?jīng)]有數(shù)據(jù)時(shí)拋出StopIteration錯(cuò)誤沮稚∫照樱可以把這個(gè)數(shù)據(jù)流看做是一個(gè)有序序列,但我們卻不能提前知道序列的長(zhǎng)度蕴掏,只能不斷通過(guò)next()函數(shù)實(shí)現(xiàn)按需計(jì)算下一個(gè)數(shù)據(jù)障般,所以Iterator的計(jì)算是惰性的,只有在需要返回下一個(gè)數(shù)據(jù)時(shí)它才會(huì)計(jì)算盛杰。
Iterator甚至可以表示一個(gè)無(wú)限大的數(shù)據(jù)流