python基礎(十六):迭代器

一、迭代器介紹

迭代器即用來迭代取值的工具,而迭代是重複反饋過程的活動,其目的通常是爲了逼近所需的目標或結果,每一次對過程的重複稱爲一次“迭代”,而每一次迭代得到的結果會作爲下一次迭代的初始值,單純的重複並不是迭代

goods=['mac','lenovo','acer','dell','sony']

index=0
while index < len(goods):
    print(goods[index])
    index+=1

下述while循環纔是一個迭代過程,不僅滿足重複,而且以每次重新賦值後的index值作爲下一次循環中新的索引進行取值,反覆迭代,最終可以取盡列表中的值

注意:

  • 上面這個迭代方法只適合序列類型,並不適合字典、集合、文件對象的迭代取值。
  • 有人會說for循環可以對字典、文件對象、集合進行循環取值,其實for循環就用到了迭代器,因此這裏沒有用for循環爲例說明

1、可迭代對象

通過索引的方式進行迭代取值,實現簡單,但僅適用於序列類型:字符串,列表,元組。對於沒有索引的字典、集合、文件對象等非序列類型,必須找到一種不依賴索引來進行迭代取值的方式,這就用到了迭代器。

可迭代對象(Iterable)。從語法形式上講,內置有__iter__方法的對象都是可迭代對象,字符串、列表、元組、字典、集合、打開的文件都是可迭代對象。

{'name':'吳晉丞'}.__iter__
{7,8,9}.__iter__
……

2、迭代器對象

調用obj.iter()方法返回的結果就是一個迭代器對象(Iterator)
除文件對象外,字典、集合、列表等都只是可迭代對象而已,它們可以通過調用iter方法生成迭代器對象,並進行迭代取值。但文件對象在python中使用時,直接生成的就是迭代器對象,當然它也是可迭代對象。文件對象可以直接調用next函數,只有迭代器對象才能調用next方法,因此文件對象是迭代器對象。執行迭代器對象.iter()方法得到的仍然是迭代器本身,而執行迭代器對象.next()方法就會計算出迭代器中的下一個值

>>> s={1,2,3} # 可迭代對象s
>>> i=iter(s)  # 本質就是在調用s.__iter__(),返回s的迭代器對象i,
>>> next(i) # 本質就是在調用i.__next__()
1
>>> next(i)
2
>>> next(i)
3
>>> next(i)  #拋出StopIteration的異常,代表無值可取,迭代結束,要想繼續取值,除非在重新生成一個迭代器。

爲什麼文件對象要直接設置成迭代器對象,集合、字典等不設置成迭代器對象呢?

答:首先我們應該明白迭代器這種需要一個值,next方法取一個值,這樣是降低了內存的消耗的。集合、字典等定義下來,本來就不是用來存很多、很多東西的。但是一個文件對象卻可以很大很大,因此必須直接生成迭代器對象,控制內存的消耗。

二、for循環原理

有了迭代器後,我們便可以不依賴索引迭代取值了,使用while循環的實現方式如下

dic = {'a':1,'b':2,'c':3}
d_iterator = iter(dic) #d_iterator便是一個迭代器對象,iter方法生成的就是一個迭代器對象
while True: # while循環的循環體是進行循環迭代取值的
    try:
        print(next(d_iterator))
    except(StopIteration): # 捕獲異常
        break # 異常處理

for循環又稱爲迭代循環,in後可以跟任意可迭代對象,上述while循環可以簡寫爲:

dic = {'a':1,'b':2,'c':3}
for i in dic:
	print(item)

for 循環在工作時,首先會調用可迭代對象goods內置的iter方法拿到一個迭代器對象,然後再調用該迭代器對象的next方法將取到的值賦給i,執行循環體完成一次循環,周而復始,直到捕捉StopIteration異常,結束迭代

爲什麼文件對象中也需要有iter方法呢?
它不是已經是迭代器對象了嗎,而且前面說迭代器調用iter方法屁用沒有,得到的還是本身。

答:這是一個專門爲統一for循環而設計的,因爲for循環中你不確定自己in後面到底是不是迭代器對象,難道還要判斷一下嗎?那不是太麻煩了,無論誰來,只要可迭代,我就給你iter方法一下,即使是文件對象,也不影響啥。所以文件對象也需要一個iter方法,拿去讓for循環調用。

三、迭代器的優缺點

基於索引的迭代取值,所有迭代的狀態(迭代的位置信息)都保存在了索引中,而基於迭代器實現迭代的方式不再需要索引,所有迭代的狀態就保存在迭代器中,然而這種處理方式優點與缺點並存:

1、優點

(1)爲序列和非序列類型提供了一種統一的迭代取值方式。

(2)惰性計算:迭代器對象表示的是一個數據流,可以只在需要時纔去調用next來計算出一個值,就迭代器本身來說,同一時刻在內存中只有一個值,因而可以存放無限大的數據流,而對於其他容器類型,如列表,需要把所有的元素都存放於內存中,受內存大小的限制,可以存放的值的個數是有限的

2、缺點

(1)除非取盡,否則無法獲取迭代器的長度

(2)只能取下一個值,不能回到開始,更像是'一次性的',迭代器產生後的唯一目標就是重複執行next方法直到值取盡,否則就會停留在某個位置,等待下一次調用next;若是要再次迭代同個對象,你只能重新調用iter方法去創建一個新的迭代器對象,如果有兩個或者多個循環使用同一個迭代器,必然只會有一個循環能取到值

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章