python的迭代器iterator

2021-07-27 15:44:47 字數 4610 閱讀 8023

可以被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...