可以被next函式呼叫不斷返回下乙個值的物件稱為迭代器(iterator),可以直接用於for迴圈的物件稱為可迭代物件(iterable),所有的可迭代物件均可以通過iter函式轉變為迭代器。事實上,for迴圈內部先呼叫iter()把iterable變成iterator然後再進行迴圈迭代
iterator可以用來訪問集合元素,迭代器物件從集合的首元素開始訪問,直到所有元素被訪問完結束,只能向前訪問。迭代器的乙個優點是事先不需要準備好整個迭代過程中的所有元素,僅僅在迭代到某個元素時才計算該元素,在這之前或之後,元素可以不存在或被銷毀。通過next()函式,可以取到每次yield,訪問到最後的時候,會丟擲stopiteration異常。但是,如果使用者提供了default引數之後,當取出所有元素,再次呼叫next函式會返回default,不會丟擲stopiteration異常
>>> l=[1,2,3,4]
>>> a=iter(l)
>>> next(a)
1
>>> next(a)
2 >>> next(a)
3 >>> next(a)
4 >>> next(a)
traceback (most recent call last):
file "", line 1, in
next(a)
stopiteration
>>> from collections import iterator, iterable
>>> isinstance(a, iterable)
true
>>> isinstance(a, iterator)
true
>>> isinstance(l, iterable)
true
>>> isinstance(l, iterator)
false
對於檔案物件來說,next函式也同樣適用,next函式的作用就和readline類似,都是一次讀取檔案的一行內容。但是readline讀取到末尾的時候返回的是空字串,next函式則會引發stopiteration異常
比如:>>> f=open(r'e:\sublimetext2\config.php')
>>> f.readline()
'<?php\n'
>>> next(f)
'\n'
使用for迴圈顯示讀取檔案內容:
for line in open("config.php").readlines():
print line
for迴圈實現了迭代器,迭代器每次只從物件讀取一條資料,不會造成過大的記憶體開銷。但是,它實際上是把檔案一次性載入到記憶體中再逐行列印出來。如果檔案很龐大,記憶體的開銷就大了.
更快的方法:
for line in open("config.php"):
print line
這裡沒有顯示讀取檔案,而是通過迭代器讀取每一行內容
或者這樣寫:
with open(r'e:\sublimetext2\config.php') as f:
for line in f:
print line
前面提到for迴圈實際上就是對可迭代物件轉換為迭代器,然後通過呼叫next函式來實現遍歷,我們可以將二者做過等價替換:
for a in [1,2,3]:
print a
<*****>
b=iter([1,2,3])
try:
while 1:
print next(b)
except stopiteration:
pass
因此我們也可以總結出:
凡是可作用於for迴圈的物件都是iterable型別;
凡是可作用於next()函式或者__next__()方法的都是iterator型別
自定義迭代器的大概過程是這樣的:
def iter(obj):
return obj.__iter__()
#python2:
def next(obj):
return obj.next()
#python3
def next(obj):
return obj.__next__()
可迭代物件內部一定是包含了__iter__()的魔法方法,list物件內部就一定存在__iter__()方法,__iter__()就是返回iterator例項的
next()函式只是呼叫了物件的__next__()(或者next())方法,list物件內部一定不存在__next__()方法,迭代器一定存在__next__()
所以,當我們要將iterable轉換為iterator的時候,可以使用iterator=iterable.__iter__(),比如a=l.__iter__()
當我們使用「iterable.__next__()」(比如l.__next__())的時候會報錯,當使用」iterator.__next__()」 (a.__next__(),python2用a.next())的時候不報錯。
迭代器(iterator)必須至少要定義 __iter__() 和 __next__() 兩個方法
class iterator:
def __init__(self):
self.start=-1
def __next__(self):
res=self.start
self.start +=3
if res >10:
raise stopiteration
return res
def __iter__(self):
return self
>>> a=iterator()
>>> print(list(a))
[-1, 2, 5, 8]
上面是python3版本,下面是python2版本
>>> class iterator:
def __init__(self):
self.start=-1
def next(self):
res=self.start
self.start +=3
if res >10:
raise stopiteration
return res
def __iter__(self):
return self
>>> a=iterator()
>>> print list(a)
[-1, 2, 5, 8]
通過上面你可以注意到__iter__的返回值都是self,事實上,當使用者自定義迭代器的時候__iter__返回的就是物件自身
自定義迭代器的時候,通過在類裡面定義乙個__iter__和__next__方法,用第乙個來返回第二個的返回物件
只要是實現了__iter__()方法的物件,就可以使用迭代器進行訪問
也行會問,既然for迴圈實際上就是用了迭代器的原理,那麼迭代器還有什麼不可替代或者提供比較好的處理方案的情況呢?
1.對於那些支援隨機訪問的資料結構,比如list、tuple還有dict,迭代器對比for並沒有優勢,而且還缺失了索引值(儘管可以使用內建函式enumerate找回索引,但是也增加了繁瑣度)。但是,對於無法隨機訪問的資料結構set(),迭代器是唯一的訪問元素方式。
比如:>>> s=
>>> a=s.__iter__()
>>> a.next()
'a'
>>> a.next()
'c'
>>> a.next()
'b'
2.節省記憶體空間,前面提到事先不需要準備好整個迭代過程中的所有元素,對於資料龐大的結構和檔案,迭代器是一種理想的訪問方式。如果我們是要對xml檔案進行處理的時候,由於etree.iterparse序列化的xml tree是可迭代物件,我們可以漸進式的處理內容
Python從放棄到入門 迭代器iterator
通過for迴圈來遍歷乙個list或tuple,這種遍歷我們稱為迭代 iteration 因此,可用於for in迴圈的物件被稱為可迭代 iterable 物件。例如 前面介紹的python內建的資料結構列表 元組 字典 集合,還有字串 range 生成器都是可迭代物件,而整數型別不是可迭代物件。如何...
iter a 2 迭代器與zip()應用
iter 是python中的迭代器,不太使用,下面展示兩種功能。1.用於簡單迭代 in 53 a out 53 1,2,3,4,5,6 in 54 b iter a in 55 list b out 55 1,2,3,4,5,6 in 57 type b out 57 list iterator2....
java無重集合Set與迭代器Iterator
set介面 t型元素的集合,不允許包含相等元素 int size 返回集合的元素個數。boolean isempty 如果集合為空,則返回true.boolean contains object o 如果集合包含與o相等的元素,則返回true.boolean containsall collecti...