轉載自 http://blog.csdn.net/bluebird_237/article/details/38894617python
迭代器就是重複地作一些事情,能夠簡單的理解爲循環,在python中實現了__iter__方法的對象是可迭代的,實現了next()方法的對象是迭代器,這樣提及來有點拗口,實際上要想讓一個迭代器工做,至少要實現__iter__方法和next方法。不少時候使用迭代器完成的工做使用列表也能夠完成,可是若是有不少值列表就會佔用太多的內存,並且使用迭代器也讓咱們的程序更加通用、優雅、pythonic。程序員
若是一個類想被用於for ... in
循環,相似list或tuple那樣,就必須實現一個__iter__()
方法,該方法返回一個迭代對象,而後,Python的for循環就會不斷調用該迭代對象的next()
方法拿到循環的下一個值,直到遇到StopIteration錯誤時退出循環。函數
咱們以斐波那契數列爲例,寫一個Fib類,能夠做用於for循環:工具
class Fib(object): def __init__(self): self.a, self.b = 0, 1 # 初始化兩個計數器a,b def __iter__(self): return self # 實例自己就是迭代對象,故返回本身 def next(self): self.a, self.b = self.b, self.a + self.b # 計算下一個值 if self.a > 100000: # 退出循環的條件 raise StopIteration(); return self.a # 返回下一個值
如今,試試把Fib實例做用於for循環:fetch
>>> for n in Fib(): ... print n ... 1 1 2 3 5 ... 46368 75025
迭代器是一個對象,而生成器是一個函數,迭代器和生成器是python中兩個很是強大的特性,編寫程序時你能夠不使用生成器達到一樣的效果,可是生成器讓你的程序更加pythonic。建立生成器很是簡單,只要在函數中加入yield語句便可。函數中每次使用yield產生一個值,函數就返回該值,而後中止執行,等待被激活,被激活後繼續在原來的位置執行。下邊的例子實現了一樣的功能:spa
根本上說, 迭代器就是有一個 next() 方法的對象, 而不是經過索引來計數. 當你或是一個循環機制(例如 for 語句)須要下一個項時, 調用迭代器的 next() 方法就能夠得到它. 條目所有取出後, 會引起一個 StopIteration 異常, 這並不表示錯誤發生, 只是告訴外部調用者, 迭代完成..net
不過, 迭代器也有一些限制. 例如你不能向後移動, 不能回到開始, 也不能複製一個迭代器.若是你要再次(或者是同時)迭代同個對象, 你只能去建立另外一個迭代器對象. 不過, 這並不糟糕,由於還有其餘的工具來幫助你使用迭代器. code
reversed() 內建函數將返回一個反序訪問的迭代器. enumerate() 內建函數一樣也返回迭代器.另外兩個新的內建函數, any() 和 all() , 在 Python 2.5 中新增, 若是迭代器中某個/全部條目的值都爲布爾真時,則它們返回值爲真. 本章先前部分咱們展現瞭如何在 for 循環中經過索引或是可迭代對象來遍歷條目. 同時 Python 還提供了一整個 itertools 模塊, 它包含各類有用的迭代器.對象
迭代器工做原理
若是這是一個實際應用程序, 那麼咱們須要把代碼放在一個 try-except 塊中. 序列如今會自
動地產生它們本身的迭代器, 因此一個 for 循環: blog
其實是這樣工做的:
另外, Python 還引進了三個新的內建字典方法來定義迭代: myDict.iterkeys() (經過 keys 迭
代), myDict.itervalues() (經過 values 迭代), 以及 myDicit.iteritems() (經過 key/value 對來迭代). 注意, in 操做符也能夠用於檢查字典的 key 是否存在 , 以前的布爾表達式myDict.has_key(anyKey) 能夠被簡寫爲 anyKey in myDict .
===文件===
文件對象生成的迭代器會自動調用 readline() 方法. 這樣, 循環就能夠訪問文本文件的全部
行. 程序員可使用 更簡單的 for eachLine in myFile 替換 for eachLine in myFile.readlines() :
記住,在迭代可變對象的時候修改它們並非個好主意. 這在迭代器出現以前就是一個問題.
一個流行的例子就是循環列表的時候刪除知足(或不知足)特定條件的項:
除列表外的其餘序列都是不可變的, 因此危險就發生在這裏. 一個序列的迭代器只是記錄你當前到達第多少個元素, 因此若是你在迭代時改變了元素, 更新會當即反映到你所迭代的條目上.在迭代字典的 key 時, 你絕對不能改變這個字典. 使用字典的 keys() 方法是能夠的, 由於keys() 返回一個獨立於字典的列表. 而迭代器是與實際對象綁定在一塊兒的, 它將不會繼續執行下去:
這樣能夠避免有缺陷的代碼. 更多有關迭代器的細節請參閱 PEP 234 .
對一個對象調用 iter() 就能夠獲得它的迭代器. 它的語法以下:
若是你傳遞一個參數給 iter() , 它會檢查你傳遞的是否是一個序列, 若是是, 那麼很簡單:
根據索引從 0 一直迭代到序列結束. 另外一個建立迭代器的方法是使用類, 咱們將在第 13 章詳細
介紹, 一個實現了 __iter__() 和 next() 方法的類能夠做爲迭代器使用.
若是是傳遞兩個參數給 iter() , 它會重複地調用 func , 直到迭代器的下個值等於sentinel .