Iterator是迭代器的意思,它的做用是一次產生一個數據項,直到沒有爲止。這樣在 for 循環中就能夠對它進行循環處理了。那麼它與通常的序列類型(list, tuple等)有什麼區別呢?它一次只返回一個數據項,佔用更少的內存。但它須要記住當前的狀態,以便返回下一數據項。它是一個有着next()方法的對象。而序列類型則保存了全部的數據項,它們的訪問是經過索引進行的。python
迭代器是一個實現了迭代器協議的對象,Python中的迭代器協議就是有next方法的對象會前進到下一結果,而在一系列結果的末尾是,則會引起StopIteration。數組
在for循環中,Python將自動調用工廠函數iter()得到迭代器,自動調用next()獲取元素,還完成了檢查StopIteration異常的工做。數據結構
經常使用的幾個內建數據結構tuple、list、set、dict都支持迭代器,字符串也可使用迭代操做。函數
你也能夠本身實現一個迭代器,如上所述,只須要在類的__iter__方法中返回一個對象,這個對象擁有一個next()方法,這個方法能在恰當的時候拋出StopIteration異常便可。可是須要本身實現迭代器的時候很少,即便須要,使用生成器會更輕鬆。性能
#!/usr/bin/env python # coding=utf-8 class test: def __init__(self, input_list): self.list = input_list self.i = 0 def __iter__(self): return self def next(self): if self.i == len(self.list): self.i = 0 raise StopIteration self.i += 1 return self.list[self.i - 1]
使用迭代器一個顯而易見的好處就是:每次只從對象中讀取一條數據,不會形成內存的過大開銷。spa
例如:設計
/* 把文件一次加載到內存中,而後逐行打印。當文件很大時,這個方法的內存開銷就很大了 */ for line in open("test.txt").readlines(): print line /* 這是最簡單也是運行速度最快的寫法,他並沒顯式的讀取文件,而是利用迭代器每次讀取下一行 */ for line in open("test.txt"): #use file iterators print line
生成器是建立迭代器的一種簡便的方法。生成器是一個特殊的函數。咱們能夠從靜態和動態兩個角度理解生成器函數。code
首先,從靜態的角度,生成器函數在代碼中表現爲:對象
其次,從動態的角度,生成器函數在運行過程當中:blog
特別的,生成器返回的迭代器,其__iter__返回其自身。
生成器的編寫方法和函數定義相似,只是在return的地方改成yield。
生成器中能夠有多個yield。當生成器遇到一個yield時,會暫停運行生成器,返回yield後面的值。當再次調用生成器的時候,會從剛纔暫停的地方繼續運行,直到下一個yield。
生成器自身又構成一個迭代器,每次迭代時使用一個yield返回的值。
須要注意的是,生成器中不須要return語句,不須要指定返回值,在生成器中已經存在默認的返回語句
生成器表達式
(i for i in range(5)) // 返回迭代器 <generator object <genexpr> at 0x7ff3e8f0d960>
列表解析,返回list
[i for i in range(5)] // 返回list [0, 1, 2, 3, 4]
在這裏存在一個問題,那就是range(5)會返回一個長度爲5的數據,若是是range(1000)那麼就會佔用一個1000大小的數組空間;若是咱們採用`生成器`,在須要的時候產生一個數字,那麼空間的佔用狀況就會下降,這裏咱們可使用xrange()函數來實現。
''' xrange 函數說明:用法與range徹底相同,所不一樣的是生成的不是一個數組,而是一個生成器。 xrange示例: ''' >>> xrange(5) xrange(5) >>> list(xrange(5)) [0, 1, 2, 3, 4] >>> xrange(1,5) xrange(1, 5) >>> list(xrange(1,5)) [1, 2, 3, 4] >>> xrange(0,6,2) xrange(0, 6, 2) >>> list(xrange(0,6,2)) [0, 2, 4]
因此xrange作循環的性能比range好,尤爲是返回很大的時候,儘可能用xrange吧,除非你是要返回一個列表。
因此,Python 2.X 的 range和xrange有何區別?答案是,range的返回值就是一個list,在你調用range的時候,Python會產生全部的元素。而xrange是一個特別設計的可迭代對象,它在創建的時候僅僅保存終止值。你可比較如下兩種寫法的實際運行結果:
for v in range(1000000000000): #possible Memory Error if v == 2: break for v in xrange(1000000000000): #fine if v == 2: break
在Python 3.X 中,再也不有內建的xrange,其range等效於Python 2.X 的xrange