美文网首页
Python中的可迭代对象、迭代器、和生成器

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

作者: 码不能停 | 来源:发表于2018-07-24 10:56 被阅读0次

    可迭代对象

    简单来讲,一个实际保存的序列,或者可以通过类似for i in [1, 2, 3, 4, 5]:类似的语法取值的对象,列表就是一个典型的可迭代对象:

    >>> my_list = [1, 2, 3, 4, 5]
    >>> for i in my_list:
    ...     print(i)
    ... 
    1
    2
    3
    4
    5
    

    for语句在此处提供了一个迭代环境,for语句通过跌打协议从可迭代对象中取出值。
    for循环执行时,实际上是获取了可迭代对象的迭代器,调用了迭代器的__next__函数,来生成序列的下一个值。当序列结束时,调用__next__函数会抛出StopIteration异常,for循环语句可以捕获这个异常,以决定何时终止循环。

    注意,可迭代对象是不可以直接调用__next__()方法的。

    >>> my_list.__next__()
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    AttributeError: 'list' object has no attribute '__next__'
    

    迭代器

    通常,我们可以通过iter()方法获取可迭代对象中的迭代器,迭代器可以直接调用__next__()方法:

    >>> li = iter(my_list)
    >>> li.__next__()
    1
    >>> iter_list = iter(my_list)
    >>> iter_list.__next__()
    1
    >>> iter_list.__next__()
    2
    >>> iter_list.__next__()
    3
    >>> iter_list.__next__()
    4
    >>> iter_list.__next__()
    5
    >>> iter_list.__next__()
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    StopIteration
    

    当迭代器结束时,调用__next__()方法会抛出StopIteration异常。
    在Pyhon3中,还提供了一个内置函数next(),可以自动调用一个对象的__next__()方法。

    >>> iter_list = iter(my_list)
    >>> next(iter_list)
    1
    >>> next(iter_list)
    2
    >>> next(iter_list)
    3
    >>> next(iter_list)
    4
    >>> next(iter_list)
    5
    >>> next(iter_list)
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    StopIteration
    

    同样地,内置next()方法也不可以直接用于可迭代对象。

    >>> next(my_list)
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    TypeError: 'list' object is not an iterator
    

    报错显示list对象不是一个迭代器。

    生成器

    生成器提供了一个在需要的时候才产生结果的工具,而不是立即产生结果,可以通过两种方式来创建

    • 生成器函数
      例如:
    def squares(n):
        for i in range(n):
            yield = i ** 2
    

    yield语句会挂起该函数,并向调用者发送一个值,并且保存函数当前的执行状态,类似于上下文,使得函数能够在离开的地方继续执行。
    当函数包括一条yield语句时, 会自动编译称为生成器,当调用时,会返回一个生成器对象,该对象支持使用__next__()方法来自动执行接口,并且在结束时抛出StopIteration异常

    • 生成器表达式
      生成器表达式与列表解析表达式十分相似
    >>> [x ** 2 for x in range(4)]
    [0, 1, 4, 9]
    

    上面的语句是一个列表解析表达式,返回一个列表。

    >>> (x ** 2 for x in range(4))
    <generator object <genexpr> at 0x1030cfe60>
    

    将中括号改为小括号,这条语句就变成了一个生成器表达式,如果想保存并且使用该表达式,需要使用一个变量接收。

    >>> x = (x ** 2 for x in range(4))
    >>> x.__next__()
    0
    >>> next(x)
    1
    >>> x.__next__()
    4
    >>> next(x)
    9
    >>> x.__next__()
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    StopIteration
    
    • 简单来讲,生成器可以认为是对内存的优化,不是一次性产生所有结果, 而是将循环过程分散到了每一次调用,在处理非常大的结果集合运算时,是最优的选择。

    相关文章

      网友评论

          本文标题:Python中的可迭代对象、迭代器、和生成器

          本文链接:https://www.haomeiwen.com/subject/oljemftx.html