Python 中iterator

The two methods correspond to two distinct protocols:
1. An object can be iterated over with "for" if it implements__iter__() or __getitem__().如果你想讓他能夠按照for的形式進行迭代,就需要定以__iter__方法。
2. An object can function as an iterator if it implements next(). Container-like objects usually support protocol 1.  Iterators are currently required to support both protocols.  The semantics of iteration come only from protocol 2; protocol 1 is present to make iterators behave like sequences; in particular so that code receiving an iterator can use a for-loop over the iterator.一個對象只要定義了next()方法可以像一個迭代器一樣運行,但是像列表,元組之類的元素的容器的話通常也支持協議1,現在的迭代器一般都支持兩個協議,但是含義上的迭代其僅僅需要支持協議2就行。協議1的目的就是能夠像序列一樣,能夠通過for-loop的方式進行遍歷
Classes can define how they are iterated over by defining an __iter__() method; this should take no additional arguments and return a valid iterator object.  A class that wants to be an iterator should implement two methods: a next() method that behaves as described above, and an__iter__()method that returns self. 一個類可以通過定義方法__iter__來指定它迭代的方式,這個方法不接受額外的參數,並且返回一個有效的迭代器對象。一個類如果像成爲一個迭代器的話,需要定義兩個方法,一個是next(),另一個是iter()返回它自己。

內置的對象跟上面所說的有點不太一樣,因爲我們沒有辦法想自定義的類一樣,我們可以對它添加一個next()方法,而我們必須對它們進行iter()調用以後才能夠成爲一個iterator,才能夠進行next(i)或for循環操作。

通常的iterator與for關鍵字配合使用,for語句在容器對象中調用__iter__()函數返回一個定義了next()或__next__()方法的iterator。通過iterator的next()或__next__()方法來在容器中逐一訪問元素,沒有後續元素,next()或__next__()就會發出警告信息StopIterator,告知for循環結束。它只會在我們進行next(i)纔會顯示,而for循環自動接受了這個警告然後結束。

只有當你擁有這兩個方法的時候你才能夠進行迭代,我們平常說列表,元組等是一個可迭代對象比如下面的例子。

for i in A的流程:

步驟1:先調用方法iter(A),將其轉化爲iterator對象; 然後對iter(A)調用next(iter(A))方法,返回值給i;

步驟2:次就是對該iterator對象進行next方法調用,如此循環進行步驟2,直到沒有元素可以迭代,返回‘StopIterator’ 提示迭代結束

>>> for i in (1,2,3):
... 	print(i)
... 
1
2
3
對內置對象,我們必須先對in後面的對象進行iter()方法的調用,然後纔會產生一個擁有next()方法的對象,然後執行iter()返回對象的next方法,賦值給target variable.然後循環這種操作,從而實現迭代。

>>> a=(1,2,3)
>>> next(a)
TypeError: tuple object is not an iterator
>>> dir(a)                      # tuple只有iter/init方法,並沒有next方法
['__add__', ..., '__init__', '__iter__', ..., 'count', 'index'] 

>>> i=iter(a)                   # 把元組(1,2,3)轉換成迭代對象
>>> dir(i)                      # 檢查發現i多了一個__next__方法
['__class__', ... '__init__', '__iter__', ... '__next__', ...]

>>> next(i)
1
>>> next(i)
2
>>> next(i)
3
>>> next(i)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
StopIteration

自定義fibonacci檢驗for循環處理的流程

class Fib:
    def __init__(self,max,min):        #多加一個參數min,我是想檢驗是不是實參是不是與init進行對應
        self.max = max                 #通過這種方式把max設置爲自己的狀態信息,因爲max對下面是不可見的 
        self.min = min         
        print ('%d: from init' % max)
        print ('%d: from init' % min)
    def __iter__(self):
        self.a = 0
        self.b = 1
        print(self.max)                #在這裏max不可見,只能訪問self.max這個函數狀態信息
        print(self.min)
        return self
    def __next__(self):                #在python3必須定義爲__next__,在python2可以定義爲next()方法 
        fib = self.a
        if fib > self.max:
            raise StopIteration
        self.a , self.b = self.b, self.a + self.b
        return fib
測試用例及輸出結果

>>> for i in Fib(4,9):
... 	print(i, end=', ')
... 
4: from init                #init只會在剛開始訪問一次
9: from init
4                           #iter也只是訪問一次 
9
0, 1, 1, 2, 3, >>>          #對iterator對象迭代進行next()操作

下面的例子用於說明我們概念上的iterator,只需類擁有next()方法就行(針對自定義對象)

class Fib:
    def __init__(self,max):
        self.max = max
        self.a =0
        self.b =1
        
    def __next__(self):
        fib = self.a
        if fib > self.max:
            raise StopIteration
        self.a , self.b = self.b, self.a + self.b
        return fib
    
運行用例及輸出結果

>>> i=Fib(4)
>>> next(i)
0
>>> next(i)
1
>>> next(i)
1

參考文獻

PEP 234 -- Iterators

5.5. Iterator Types

http://www.cnblogs.com/itech/archive/2011/01/19/1939119.html

Learning python


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章