Python中Iterator迭代器的使用雜談
迭代器是一種支持next()操作的對(duì)象。它包含一組元素,當(dāng)執(zhí)行next()操作時(shí),返回其中一個(gè)元素;當(dāng)所有元素都被返回后,生成一個(gè)StopIteration異常。
>>>a=[1,2,3] >>>ia=iter(a) >>>next(ia) 1 >>>next(ia) 2 >>>next(ia) 3 >>>next(ia) Traceback (most recent call last): File "<stdin>", line 1, in <module> StopIteration
ite()可以接受多種Python對(duì)象為參數(shù),比如list,tuple, dict, set等,并將其轉(zhuǎn)化為迭代器。迭代器可以用于for語(yǔ)句或in語(yǔ)句中。很多常用操作也是支持迭代器的,比如sum(), max()等。
>>> b=[4,5,6] >>> ib=iter(b) >>> for x in ib: ... print(x) ... 4 5 6 >>> ic=iter(b) >>> sum(ic) 15 >>> id=iter(b) >>> max(ic) 6
毋庸置疑,迭代器有很多好處:
1.“流式”數(shù)據(jù)處理方式減少內(nèi)存消耗:
比如處理文件,一下猛地把全部數(shù)據(jù)全部取出來放到內(nèi)存里面進(jìn)行處理會(huì)導(dǎo)致程序消耗大量?jī)?nèi)存,有時(shí)甚至沒法做到,一般我們會(huì)一部分一部分的對(duì)文件內(nèi)容進(jìn)行處理:
for text_line in open("xx.txt"):
print text_line
2.或者對(duì)xml文件進(jìn)行處理的時(shí)候:
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對(duì)象和etree.iterparse序列化的xml tree都是可迭代對(duì)象,能夠讓我們漸進(jìn)式地對(duì)文件的內(nèi)容進(jìn)行處理。
3.支持方便用for語(yǔ)句對(duì)數(shù)據(jù)進(jìn)行消費(fèi):
python內(nèi)置的一些常見的像類型像數(shù)組、列表甚至字符串等都是可迭代類型,這樣我們就能方便for語(yǔ)句這個(gè)語(yǔ)法糖方便對(duì)數(shù)據(jù)進(jìn)行消費(fèi),不需要自己記錄索引位置,人肉循環(huán):
for i in [1, 2, 3, 4] print i,
簡(jiǎn)單了解了一下迭代器的好處后,我們正正經(jīng)經(jīng)的聊聊python的迭代器模式。
在這里我們引入兩個(gè)比較繞口的名詞:可迭代對(duì)象和迭代器對(duì)象,個(gè)人覺得從這兩個(gè)概念下手會(huì)對(duì)迭代器有比較好的理解。在放例子前先對(duì)這兩個(gè)概念給一個(gè)不入流的解釋:
可迭代對(duì)象:對(duì)象里面包含__iter()__方法的實(shí)現(xiàn),對(duì)象的iter函數(shù)經(jīng)調(diào)用之后會(huì)返回一個(gè)迭代器,里面包含具體數(shù)據(jù)獲取的實(shí)現(xiàn)。
迭代器:包含有next方法的實(shí)現(xiàn),在正確范圍內(nèi)返回期待的數(shù)據(jù)以及超出范圍后能夠拋出StopIteration的錯(cuò)誤停止迭代。
放個(gè)例子邊看邊說:
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是一個(gè)可迭代對(duì)象,所以我們也能夠?qū)λ胒or語(yǔ)句來進(jìn)行迭代:
temp = my_range(10) for item in temp: print item,
輸出:
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ì)地看一下輸出的日志:
- 數(shù)據(jù)確實(shí)是“流式”處理的
- iterator是真正在背后做事的人
- for語(yǔ)句能夠非常方便的迭代對(duì)象的數(shù)據(jù)。
可迭代對(duì)象其實(shí)更像是整個(gè)迭代器模式模式的上層,像一種約束一種契約一種規(guī)范,它能夠保證自己能夠返回一個(gè)在實(shí)際工作中干活的迭代器對(duì)象。for、sum等接受一個(gè)可迭代對(duì)象的方法都是遵循這樣的規(guī)范:調(diào)用對(duì)象的__iter__函數(shù),返回迭代器,對(duì)迭代器對(duì)象返回的每個(gè)值進(jìn)行處理抑或需要一些匯總的操作。拿for舉個(gè)例子:
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這個(gè)語(yǔ)法糖背后的邏輯差不多就是上面例子中代碼所示的那樣:首先獲取可迭代對(duì)象返回的迭代器對(duì)象,然后調(diào)用迭代器對(duì)象的next方法獲取每個(gè)值,在獲取值的過程中隨時(shí)檢測(cè)邊界-也就是檢查是否拋出了StopIteration這樣的錯(cuò)誤,如果迭代器對(duì)象拋出錯(cuò)誤則迭代停止(note:從這個(gè)例子可以看出,對(duì)于那些接受可迭代對(duì)象的方法,如果我們傳一個(gè)單純的迭代器對(duì)象其實(shí)也是無法工作的,可能會(huì)報(bào)出類似于TypeError: iteration over non-sequence的錯(cuò)誤)。
當(dāng)然了,一般在應(yīng)用過程中我們不會(huì)將他們特意的分開,我們能夠稍微對(duì)迭代器對(duì)象進(jìn)行修改一下,添加__iter__方法的實(shí)現(xiàn),這樣對(duì)象本身就既是可迭代對(duì)象也是一個(gè)迭代器對(duì)象了:
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
輸出:
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
相關(guān)文章
python-Web-flask-視圖內(nèi)容和模板知識(shí)點(diǎn)西寧街
在本篇文章里小編給大家分享了關(guān)于python-Web-flask-視圖內(nèi)容和模板的相關(guān)知識(shí)點(diǎn)內(nèi)容,有需要的朋友們參考學(xué)習(xí)下。2019-08-08
Python基礎(chǔ)實(shí)戰(zhàn)總結(jié)
今天要給大家介紹的是Python基礎(chǔ)實(shí)戰(zhàn),本文主要以舉例說明講解:?jiǎn)栴}的關(guān)鍵點(diǎn)就是在于構(gòu)造姓名,學(xué)號(hào)和成績(jī),之后以字典的形式進(jìn)行寫入文件。這里準(zhǔn)備兩個(gè)列表,一個(gè)姓,一個(gè)名,之后使用random庫(kù)進(jìn)行隨機(jī)字符串拼接,得到姓名,需要的朋友可以參考一下2021-10-10
mac PyCharm添加Python解釋器及添加package路徑的方法
今天小編就為大家分享一篇mac PyCharm添加Python解釋器及添加package路徑的方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2018-10-10
用Python實(shí)現(xiàn)最速下降法求極值的方法
今天小編就為大家分享一篇用Python實(shí)現(xiàn)最速下降法求極值的方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2019-07-07
Python cookbook(數(shù)據(jù)結(jié)構(gòu)與算法)通過公共鍵對(duì)字典列表排序算法示例
這篇文章主要介紹了Python cookbook(數(shù)據(jù)結(jié)構(gòu)與算法)通過公共鍵對(duì)字典列表排序算法,結(jié)合實(shí)例形式分析了Python基于operator模塊中的itemgetter()函數(shù)對(duì)字典進(jìn)行排序的相關(guān)操作技巧,需要的朋友可以參考下2018-03-03

