python迭代器與iter()函數實例教程


python迭代器與iter()函數實例教程

發布時間:2014-07-16編輯: 腳本學堂
本文介紹了python迭代器與iter()函數的用法,Python 的迭代無縫地支持序列對象,而且它還允許程序員迭代非序列類型,包括用戶定義的對象。
 

迭代器是在版本 2.2 被加入 Python 的,它為類序列對象提供了一個類序列的接口。
序列是一組數據結構,你可以利用它們的索引從0 開始一直“迭代“ 到序列的最后一個條目。
用“計數“的方法迭代序列是很簡單的。
Python 的迭代無縫地支持序列對象,而且它還允許程序員迭代非序列類型,包括用戶定義的對象。

迭代器用起來很靈巧,可以迭代不是序列但表現出序列行為的對象,例如字典的 key,一個文件的行等。
當使用循環迭代一個對象條目時,幾乎不可能分辨出它是迭代器還是序列。不必去關注這些,因為 Python 讓它象一個序列那樣操作。

如何迭代?

迭代器就是有一個 next() 方法的對象,而不是通過索引來計數。當你或是一個循環機制(例如 for 語句)需要下一個項時,調用迭代器的 next() 方法就可以獲得它。條目全部取出后,會引發一個 StopIteration 異常,這並不表示錯誤發生,只是告訴外部調用者,迭代完成.

不過,迭代器也有一些限制。例如你不能向后移動,不能回到開始,也不能復制一個迭代器.如果你要再次(或者是同時)迭代同個對象,你只能去創建另一個迭代器對象。不過,這並不糟糕,因為還有其他的工具來幫助你使用迭代器。(www.jbxue.com 腳本學堂 整理)

reversed() 內建函數將返回一個反序訪問的迭代器。enumerate() 內建函數同樣也返回迭代器.另外兩個新的內建函數,any() 和 all() ,在 Python 2.5 中新增,如果迭代器中某個/所有條目的值都為布爾真時,則它們返回值為真。本章先前部分展示了如何在 for 循環中通過索引或是可迭代對象來遍歷條目。同時 Python 還提供了一整個 itertools 模塊,它包含各種有用的迭代器.

一,使用迭代器

===序列===

正如先前提到的,迭代 Python 的序列對象和你想像的一樣:
 

復制代碼代碼示例:
>>> myTuple = (123,‘xyz’,45.67)
>>> i = iter(myTuple)
>>> i.next()
123
>>> i.next()
‘xyz’
>>> i.next()
45.67
>>> i.next()
Traceback (most recent call last):
File “<stdin>”,line 1,in <module>
StopIteration
 

如果這是一個實際應用程序,那么需要把代碼放在一個 try-except 塊中。序列現在會自動地產生它們自己的迭代器,所以一個 for 循環: 
 

復制代碼代碼示例:
for i in seq:
    do_something_to(i)

實際工作方式:
 

復制代碼代碼示例:
fetch = iter(seq)
while True:
try:
i = fetch.next()
except StopIteration:
break
do_something_to(i)
 

不過不需要改動你的代碼,因為 for 循環會自動調用迭代器的 next() 方法(以及監視StopIteration 異常)。

===字典===

字典和文件是另外兩個可迭代的 Python 數據類型。字典的迭代器會遍歷它的鍵(keys).
語句 for eachKey in myDict.keys() 可以縮寫為 for eachKey in myDict ,例如:
 

復制代碼代碼示例:
>>> legends = { (‘Poe’,‘author’): (1809,1849,1976),
… (‘Gaudi’,‘architect’): (1852,1906,1987),
… (‘Freud’,‘psychoanalyst’): (1856,1939,1990)
… }

>>> for eachLegend in legends:
… print ‘Name: %stOccupation: %s‘ % eachLegend
… print ‘ Birth: %stDeath: %stAlbum: %sn‘
… % legends[eachLegend]

Name: Freud Occupation: psychoanalyst
Birth: 1856 Death: 1939 Album: 1990
Name: Poe Occupation: author
Birth: 1809 Death: 1849 Album: 1976
Name: Gaudi Occupation: architect
Birth: 1852 Death: 1906 Album: 1987

另外,Python 還引進了三個新的內建字典方法來定義迭代:
myDict.iterkeys() (通過 keys 迭代),myDict.itervalues() (通過 values 迭代),以及 myDicit.iteritems() (通過 key/value 對來迭代)。(www.jbxue.com 腳本學堂 整理)

注意,in操作符也可以用於檢查字典的 key 是否存在,之前的布爾表達式myDict.has_key(anyKey) 可以被簡寫為 anyKey in myDict。

===文件===

文件對象生成的迭代器會自動調用 readline() 方法。
這樣循環就可以訪問文本文件的所有行。程序員可以使用 更簡單的 for eachLine in myFile 替換 for eachLine in myFile.readlines():
 

復制代碼代碼示例:
>>>myFile=open(‘config-win.txt’)
 
>>> for eachLine in myFile:
… print eachLine,# comma suppresses extra n

[EditorWindow]
font-name: courier new
font-size: 10
>>> myFile.close()

二,可變對象和迭代器

記住,在迭代可變對象的時候修改它們並不是個好主意。這在迭代器出現之前就是一個問題。
一個流行的例子就是循環列表的時候刪除滿足(或不滿足)特定條件的項:
 

復制代碼代碼示例:
for eachURL in allURLs:
    if not eachURL.startswith(‘http://’):
        allURLs.remove(eachURL) # YIKES!!
 

除列表外的其他序列都是不可變的,所以危險就發生在這里。一個序列的迭代器只是記錄你當前到達第多少個元素,所以如果你在迭代時改變了元素,更新會立即反映到你所迭代的條目上.在迭代字典的 key 時,你絕對不能改變這個字典。使用字典的 keys() 方法是可以的,因為keys() 返回一個獨立於字典的列表。而迭代器是與實際對象綁定在一起的,它將不會繼續執行下去:
 

復制代碼代碼示例:
>>> myDict = {‘a’: 1,‘b’: 2,‘c’: 3,‘d’: 4}
>>> for eachKey in myDict:
… print eachKey,myDict[eachKey]
… del myDict[eachKey]
… a 1
Traceback (most recent call last):
File “<stdin>”,line 1,in <module>
RuntimeError: dictionary changed size during iteration
 

這樣可以避免有缺陷的代碼。更多有關迭代器的細節請參閱 PEP 234 .

三,如何創建迭代器

對一個對象調用 iter() 就可以得到它的迭代器。它的語法如下:
iter(obj)
iter(func,sentinel)
如果傳遞一個參數給 iter() ,它會檢查你傳遞的是不是一個序列,如果是,那么很簡單: 
根據索引從 0 一直迭代到序列結束。另一個創建迭代器的方法是使用類,將在第 13 章詳細介紹,一個實現了 __iter__() 和 next() 方法的類可以作為迭代器使用.
如果是傳遞兩個參數給 iter() ,它會重復地調用 func ,直到迭代器的下個值等於sentinel。

 
 
 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM