16、迭代器
一、迭代器介紹
- 可迭代物件
- 迭代器物件
二、for迴圈原理
三、迭代器的優缺點
- 優點
- 缺點
一 迭代器介紹
迭代器即用來迭代取值的工具,而迭代是重複反饋過程的活動,其目的通常是為了逼近所需的目標或結果,每一次對過程的重複稱為一次”迭代“,而每一次迭代得到的結果會作為下一次迭代的初始值,單純的重複並不是迭代
while Ture:
msg = input('>>>:').strip()
print(msg)
下述while迴圈才是一個迭代過程,不僅滿足重複,而且以每次重新賦值後的index值作為下一次迴圈中的新的索引進行取值,反覆迭代,最終可以取盡列表中的值
goods = ['mac', 'lenovo', 'acer', 'dell', 'sony']
index = 0
while index < len(goods):
print(goods(index))
index += 1
可迭代物件
通過索引的方式進行迭代取值,實現簡單,但僅使用於序列型別:字串,列表,元組。對於沒有索引的字典、集合等非序列型別,必須找到一種不依賴索引來進行迭代取值的方式,這就用到了迭代器。
要想了解迭代器為何物,必須事先搞清楚一個很重要的概念:可迭代物件(Iterable)。從語法形式上講,內建有__iter__方法的物件都是可迭代物件,字串、列表、元組、字典、集合、開啟的檔案都是可迭代物件:
{'name':'egon'}.__iter__
{7, 8, 9}.__iter__
......
迭代器物件
呼叫obj.iter()方法返回的結果就是一個迭代器物件(Iterator)。迭代器物件是內建有iter和next方法的物件,開啟的檔案本身就是一個迭代器物件,執行迭代器物件.iter()方法得到的仍然是迭代器本身,不依賴於索引的迭代取值方式,只要存在多個”值“,無論序列型別還是非序列型別都可以按照迭代器的方式取值
>>> s = {1, 2, 3} # 可迭代物件s >>> i = iter(s) # 本質就是載呼叫s.__iter__(),返回s的迭代器物件 >>> next(i) # 本質就是再呼叫i.__next__() 1 >>> next(i) 2 >>> next(i) 3 >>> next(i) # 丟擲StopIteration的異常,代表無值可取,迭代結束 Traceback (most recent call last): File "<stdin>", line 1, in <module> StopIteration
for迴圈原理
有了迭代器後,我們便可以不依賴索引迭代取值了,使用while迴圈的實現方式如下
goods = ['mac', 'lenovo', 'acer', 'dell', 'sony']
i = iter(goods) # 每次都需要重新獲取一個迭代器物件
while Ture:
try:
print(next(i))
except StopIteration: # 捕捉異常終止迴圈
break
for迴圈又稱為迭代迴圈,in後可以跟任意可迭代物件,上述while迴圈可以簡寫為
goods = ['mac', 'lenovo', 'acer', 'dell', 'sony']
for item in goods:
print(item)
for迴圈再工作時,首先會呼叫可迭代物件goods內建的iter方法拿到一個迭代器物件,然後再呼叫該迭代器物件的next方法將取到的值賦給iten,執行迴圈體完成一次迴圈,周而復始,直到捕捉StopIteration異常,結束迭代。
三 迭代器的優缺點
基於索引的迭代取值,所有的狀態都儲存在了索引中,而基於迭代器實現迭代的方式不再需要索引,所有迭代的狀態就儲存在迭代器中,然而這種處理方式優點於缺點並存:
優點
- 為序列和非序列型別提供了統一的迭代取值方式。
- 惰性計算:迭代器物件表示的是一個數據流,可以只在需要時才去呼叫next來計算出一個值,就迭代器本身來說,同一時刻在記憶體中只有一個值,因而可以存放無限大的資料流,而對於其他容器型別,如列表,需要把所有的元素都存放於記憶體中,受記憶體大小的限制,可以存放的值的個數是有限的。
缺點
- 除非取盡,否則無法獲取迭代器的長度
- 只能取下一個值,不能回到開始,更像是’一次性的‘,迭代器產生後的唯一目標就是重複執行next方法直到值取盡,否則就會停留在某個位置,等待下一次呼叫next;若是要再次迭代同個物件,你只能重新呼叫iter方法去建立一個新的迭代器物件,如果有兩個或者多個迴圈使用同一個迭代器,必然只會有一個迴圈能取到值。