迭代器(Iterable)和for..in..的三种协议

Posted Python++

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了迭代器(Iterable)和for..in..的三种协议相关的知识,希望对你有一定的参考价值。

一。迭代器协议

  1.  迭代器协议:对象需要提供next方法,它要么返回迭代中的下一项,要么就引起一个StopIteration异常,以终止迭代

  2. 可跌达对象:实现了迭代器协议的对象

  3. 协议是一种约定,可迭代对象实现迭代器协议,在Python中,迭代是通过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
... 
1
1
2
3
5
8
13
21
34
55
89
>>> isinstance(a,Iterable)
True
>>> 

    Fib既是一个可迭代对象(因为它实现了__iter__方法),又是一个迭代器(因为实现了__next__方法)

   再简化一下,不用for....in....

>>> a = Fib()
>>> it = iter(a)
>>> next(it)
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
... 
0
a
1
a
2
a
3
a
4

   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
... 
a
b
c
d
e
>>> 

    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 d
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
StopIteration
>>> 

     这是生成器(generator),是可迭代对象,不是一次性列出结果,用到了才按照某种规则得出结果,占用内存很少,用for...in...时不断循环调用 next() 方法,每次 next() 后 yield 返回一个值并挂起,到下次 next() 从上次挂起的 yield 接着执行,yield 和 return 一样返回值,生成器只迭代一次,因为没有__iter__返回新的迭代对象。

以上是关于迭代器(Iterable)和for..in..的三种协议的主要内容,如果未能解决你的问题,请参考以下文章

构成可迭代对象的要素

Python的基础知识之迭代器

Python高级知识点总结

Python 可迭代的对象迭代器和生成器

python三大器之迭代器

Python生成器generator简介