一。迭代器协议
1. 迭代器协议:对象需要提供next方法,它要么返回迭代中的下一项,要么就引起一个StopIteration异常,以终止迭代
2. 可跌代对象:实现了迭代器协议的对象
3. 协议是一种约定,可迭代对象实现迭代器协议,在Python中,迭代是通过for ... in
来完成的
二。什么是可迭代对象
>>> from collections import Iterable>>> class Fib:... def __iter__(self):... pass... >>> a = Fib()>>> isinstance(a,Iterable)True>>>
实现了__iter__方法的对象就是可迭代对象,a 就是可迭代对象。
三。什么是迭代器
>>> from collections import Iterable>>> class Fib1:... def __init__(self):... self.a = 0... def next(self):... self.a = self.a + 1... if self.a > 4:... raise StopIteration()... return self.a... >>> class Fib:... def __iter__(self):... return Fib1()... >>> a = Fib()>>> b = iter(a)>>> b.next()1>>> b.next()2>>> b.next()3>>> b.next()4>>> b.next()Traceback (most recent call last): File "", line 1, in File " ", line 7, in nextStopIteration>>>
a是可迭代对象,通过 iter(a) 让解析器调用a的 __iter__ 方法返回一个迭代器让 b 接收,b 就是一个迭代器对象,所以说,迭代器就是实现了 next 方法的对象。
整合一下上面例子可得
>>> a = Fib()>>> b = iter(a)>>> while True:... try:... b.next()... except StopIteration:... break... 1234>>>
用循环调用 b 的 next 方法来迭代。
再整合一下得
>>> a = Fib()>>> for x in a:... print x... 1234>>>
可见,for...in 就是这样迭代可迭代对象的。
四。简单迭代器
以斐波那契数列为例,写一个简单的迭代器
>>> from collections import Iterable>>> class Fib:... def __init__(self):... self.a,self.b = 0,1... def __iter__(self):... return self... def next(self):... self.a,self.b = self.b,self.a + self.b... if self.a > 100:... raise StopIteration()... return self.a... >>> a = Fib()>>> for n in a:... print n... 1123581321345589>>> isinstance(a,Iterable)True>>>
Fib既是一个可迭代对象(因为它实现了__iter__
方法),又是一个迭代器对象(因为实现了next
方法)
再简化一下,不用for....in....
>>> a = Fib()>>> it = iter(a) // 解释器调用a的__iter__方法返回一个迭代器>>> next(it) // 调用it的next方法1>>> next(it)1>>> next(it)2>>> next(it)3>>>
一个迭代器只迭代一次,重复跌代要获得新的迭代器。
五。for...in... 协议
1. 协议A: __iter__ + next
这是迭代器的协议,和上面说的一样,for..in.. 先调用iter(a) 让a的__iter__返回一个迭代器,然后循环这个迭代器的next方法直到没有下一个元素异常退出。
for...in... 首先执行跌达器,比如存在跌达和__getitem__就会以跌达器遍历.
2. 协议B: __getitem__
>>> class B:... def __getitem__(self,n):... print n... time.sleep(2)... return 'a'... >>> b = B()>>> for x in b:... print x... 0a1a2a3a4
n 一直循环的增长,直到有异常此循环才退出,一般作为下标索引遍历
>>> class B:... def __init__(self):... self.l = ['a','b','c','d','e']... def __getitem__(self,n):... return self.l[n]... >>> b = B()>>> for x in b:... print x... abcde>>>
3. 协议C: yield关键字
>>> def c():... yield 'a'... yield 'b'... yield 'c'... yield 'd'... >>> c1 = c()>>> print next(c1),next(c1),next(c1),next(c1),next(c1)a b c dTraceback (most recent call last): File "", line 1, in StopIteration>>>
用for..in来
>>> c1 = c()>>> for x in c1:... print x... abcd>>>
c1是生成器(generator),是可迭代对象,当然也是迭代器对象,不是一次性列出结果,用到了才按照某种规则得出结果,占用内存很少,用for...in...时不断循环调用 next() 方法,每次 next() 后 yield 返回一个值并挂起,到下次 next() 从上次挂起的 yield 接着执行,yield 和 return 一样返回值,生成器只迭代一次。