zoukankan      html  css  js  c++  java
  • 迭代器(Iterable)和for..in..的三种协议

    一。迭代器协议

      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 "<stdin>", line 1, in <module>
      File "<stdin>", line 7, in next
    StopIteration
    >>> 

      a是可迭代对象,通过 iter(a) 让解析器调用a的 __iter__ 方法返回一个迭代器让 b 接收,b 就是一个迭代器对象,所以说,迭代器就是实现了 next 方法的对象。

      整合一下上面例子可得

    >>> a = Fib()
    >>> b = iter(a)
    >>> while True:
    ...     try:
    ...         b.next()
    ...     except StopIteration:
    ...         break
    ... 
    1
    2
    3
    4
    >>> 

      用循环调用 b 的 next 方法来迭代。

      再整合一下得

    >>> a = Fib()
    >>> for x in a:
    ...     print x
    ... 
    1
    2
    3
    4
    >>> 

      可见,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)                    // 解释器调用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
    ... 
    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
    >>> 

         用for..in来

    >>> c1 = c()
    >>> for x in c1:
    ...     print x
    ... 
    a
    b
    c
    d
    >>> 

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

  • 相关阅读:
    算法(Algorithms)第4版 练习 1.5.22
    基于RPC原理的dubbo
    java的动态代理机制详解
    xxxx interview
    mysql创建账号
    elasticsearch搜索集群基础架构
    zookeeper可视化管理工具node-zk-browser安装
    kafka监控搭建
    kafka集群安装
    zookeeper集群安装
  • 原文地址:https://www.cnblogs.com/GH-123/p/7799617.html
Copyright © 2011-2022 走看看