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()操作
从这段代码中看出,要实现for功能,自定义类与内置类是不同的,自定类不仅需要定义__iter__方法返回self对象,执行时也是只执行一次,还要实现__next__方法,for循环的机制就是不停调用__next__方法,直到__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







你可能感兴趣的:(Python中iterator的理解)