毋庸置疑可霎,迭代器有很多好處:
- “流式”數(shù)據(jù)處理方式減少內(nèi)存消耗:
比如處理文件,一下猛地把全部數(shù)據(jù)全部取出來放到內(nèi)存里面進(jìn)行處理會導(dǎo)致程序消耗大量內(nèi)存念祭,有時甚至沒法做到三幻,一般我們會一部分一部分的對文件內(nèi)容進(jìn)行處理:
for text_line in open("xx.txt"):
print text_line
或者對xml文件進(jìn)行處理的時候:
tree = etree.iterparse(xml, ['start', 'end'])
for event, elem in tree:
if event == "end"
result = etree.tostring(elem)
elem.clear()
print result
內(nèi)置函數(shù)open
返回的file
對象和etree.iterparse
序列化的xml tree都是可迭代對象,能夠讓我們漸進(jìn)式地對文件的內(nèi)容進(jìn)行處理矿微。
- 支持方便用
for
語句對數(shù)據(jù)進(jìn)行消費:
python內(nèi)置的一些常見的像類型像數(shù)組痕慢、列表甚至字符串
等都是可迭代類型,這樣我們就能方便for
語句這個語法糖方便對數(shù)據(jù)進(jìn)行消費冷冗,不需要自己記錄索引位置守屉,人肉循環(huán):
for i in [1, 2, 3, 4]
print i,
簡單了解了一下迭代器的好處后惑艇,我們正正緊緊的聊聊python的迭代器模式
在這里我們引入兩個比較繞口的名詞:可迭代對象
和迭代器對象
蒿辙,個人覺得從這兩個概念下手會對迭代器有比較好的理解拇泛。在放例子前先對這兩個概念給一個不入流的解釋:
-
可迭代對象
:對象里面包含__iter()__
方法的實現(xiàn),對象的iter
函數(shù)經(jīng)調(diào)用之后會返回一個迭代器思灌,里面包含具體數(shù)據(jù)獲取的實現(xiàn)俺叭。 -
迭代器
:包含有next
方法的實現(xiàn),在正確范圍內(nèi)返回期待的數(shù)據(jù)以及超出范圍后能夠拋出StopIteration
的錯誤停止迭代泰偿。
放個例子邊看邊說:
class iterable_range:
def __init__(self, n):
self.n = n
def __iter__(self):
return my_range_iterator(self.n)
class my_range_iterator:
def __init__(self, n):
self.i = 0
self.n = n
def next(self):
if self.i < self.n:
i = self.i
self.i += 1
print 'iterator get number:', i
return i
else:
raise StopIteration()
```
例子中的`iterable_range`是一個可迭代對象熄守,所以我們也能夠?qū)λ胒or語句來進(jìn)行迭代:
temp = my_range(10)
for item in temp:
print item,
output:
my iterator get number: 0
0
my iterator get number: 1
1
my iterator get number: 2
2
my iterator get number: 3
3
my iterator get number: 4
4
my iterator get number: 5
5
my iterator get number: 6
6
my iterator get number: 7
7
my iterator get number: 8
8
my iterator get number: 9
9
大家可以仔細(xì)地看一下輸出的日志:
1. 數(shù)據(jù)確實是“流式”處理的
2. iterator是真正在背后做事的人
3. `for`語句能夠非常方便的迭代對象的數(shù)據(jù)。
可迭代對象其實更像是整個`迭代器模式`模式的上層耗跛,像一種約束一種契約一種規(guī)范裕照,它能夠保證自己能夠返回一個在實際工作中干活的迭代器對象。`for`调塌、`sum`等接受一個可迭代對象的方法都是遵循這樣的規(guī)范:調(diào)用對象的`__iter__`函數(shù)晋南,返回迭代器,對迭代器對象返回的每個值進(jìn)行處理抑或需要一些匯總的操作羔砾。拿`for`舉個例子:
iterator_object = iterable_object.iter()
while True:
try:
value = iterator_object.next()
except StopIteration:
# StopIteration exception is raised after last element
break
# loop code
print value
**`for`**這個語法糖背后的邏輯差不多就是上面例子中代碼所示的那樣:首先獲取可迭代對象返回的迭代器對象负间,然后調(diào)用迭代器對象的`next`方法獲取每個值,在獲取值的過程中隨時檢測邊界-也就是檢查是否拋出了`StopIteration`這樣的錯誤姜凄,如果迭代器對象拋出錯誤則迭代停止(note:從這個例子可以看出政溃,對于那些接受可迭代對象的方法,如果我們傳一個單純的迭代器對象其實也是無法工作的态秧,可能會報出類似于`TypeError: iteration over non-sequence`的錯誤)董虱。
當(dāng)然了,一般在應(yīng)用過程中我們不會將他們特意的分開屿聋,我們能夠稍微對迭代器對象進(jìn)行修改一下空扎,添加`__iter__`方法的實現(xiàn),這樣對象本身就既是可迭代對象也是一個迭代器對象了:
class my_range_iterator:
def init(self, n):
self.i = 0
self.n = n
def __iter__(self):
return self
def next(self):
if self.i < self.n:
i = self.i
self.i += 1
print 'my iterator get number:', i
return i
else:
raise StopIteration()
for item in my_range_iterator(10):
print item
output:
my iterator get number: 0
0
my iterator get number: 1
1
my iterator get number: 2
2
my iterator get number: 3
3
my iterator get number: 4
4
my iterator get number: 5
5
my iterator get number: 6
6
my iterator get number: 7
7
my iterator get number: 8
8
my iterator get number: 9
9