迭代器
什麼是迭代器
- 迭代是Python最強大的功能之一,是訪問序列中元素的一種方式。
- 迭代器是一個可以記住遍歷的位置的對象。
- 迭代器對象從集合的第一個元素開始訪問,直到所有的元素被訪問完結束。迭代器只能往前不會後退。
- 迭代器有兩個基本的方法:iter() 和 next()。
可迭代對象
- 字符串、列表、元組對象等都是可迭代對象
- 字符串、列表、元組對象等都可以創建迭代器
也就是說:
字符串、列表、元組對象等暫時不是迭代器,暫時不能被迭代。但是,它們成爲迭代器之後就可以被迭代了,如for循環。
利用可迭代對象Iterable創建迭代器Iterator
l=[1,2,3,4] #l:可迭代對象
i=iter(l) #i:迭代器
print(next(i)) #輸出1
print(next(i)) #輸出2
print(i.__next__()) #輸出3
解釋:
- iter()函數可以將可迭代對象創建爲迭代器
- 利用next函數可以得到下一個元素值
- 迭代器能夠記住遍歷的位置,所以可以依次調用next()
- 可迭代對象:Iterable
- 迭代器:Iterator
- 可迭代對象不能被迭代,不能調用next()。成爲迭代器之後纔可以。
注意:
遍歷完畢後,若再次調用next()函數,則會拋出異常:StopIteration,處理此異常即可。
處理StopIteration異常
try:
l=[1,2]
i=iter(l)
print(next(i)) #輸出1
print(next(i)) #輸出2
print(next(i)) #拋出異常
except StopIteration as stopIteration:
print("遍歷完成")
刨析for循環
for循環實現了序列的遍歷,那它怎麼實現的呢?
for循環做的三件事:
- 創建迭代器
- 調用next方法
- 處理StopIteration異常
模擬for循環:
a=[100,200,300,400,500]
j=None
i=iter(a) #1.創建迭代器
while(True):
try:
j=next(i) #2.調用next方法
except StopIteration as stopIteration: #3.處理StopIteration異常
break
print(j)
結果:
100
200
300
400
500
生成器
什麼是生成器?
- 生成器是一種特殊的迭代器。
- 普通的迭代器將所有數據存放在內存中,極其佔用內存空間。
- 生成器不將數據存入內存,而是通過計算得到數據。
生成式生成器
a=(x*x for x in range(4))
print(next(a)) #輸出0
print("---------------------")
for i in a: #輸出1、4、9
print(i)
解釋:
- 生成式生成器的語法與列表生成式相似,但用小括號( )包裹。列表生成式用[ ]包裹。
- 數據不會存放在內存中,每一個調用next函數,就會計算一次數據。
- 使用生成器的好處是:節約內存空間。
函數生成器
- 函數生成器使用關鍵字yield來產生數據。
- 通過next()來得到yield產生的數據
def get():
yield 1
yield 2
g=get()
print(next(g)) #輸出1
print(next(g)) #輸出2
解釋:
- 依次產生1和2,第三次調用next()則報錯
- 運行yield語句後,python立即設置斷點,停止運行此函數,等待下一次調用next()
- 每次運行,將從上一次的斷點處(即上一個yield後)開始運行。
函數生成器-send
- 通過send函數得到下一個值
- send函數還可以傳入一個值,這個值將被yield接收到
def func():
count1 = yield 1
print("count1=" , count1)
count2 = yield 2
print("count2=" , count2)
yield 3
g = func()
print(g.send(None))
print(g.send(2))
結果:
1
count1= 2
2
解釋:
count1 = yield 1
是賦值語句,先執行等號右邊。- 運行yield語句後,暫停運行此函數,所以第一次並沒有接收值。所以第一次通過send得到值需要用send(None)。
- 此處的知識可以運用到協程上。
應用-斐波那契序列
可以得到無限多個斐波那契序列中的元素:
def fib():
a=1
b=1
yield a
yield b
while(True):
yield a+b
temp=a+b
a=b
b=temp
f = fib()
for i in range(10):
print(next(f),end=" ")
結果:
1 1 2 3 5 8 13 21 34 55