美文网首页初学者python
Python 生成器和迭代器

Python 生成器和迭代器

作者: 大梦三千秋 | 来源:发表于2020-01-21 15:14 被阅读0次

    生成器和迭代器


    生成器


    Python 列表推导和生成器表达式

    在上文中简单介绍了生成器的作用。在列表推导创建列表时,受到内存的限制,列表容量同样会受到限制,而且会极大的消耗空间。这时,一边循环一边计算这种机制,也就是生成器也就出现了。

    创建生成器

    创建生成器(generator),有很多方法。其中一种,使用生成器表达式,即是将列表推导中的方括号 [] 改成圆括号 ()

    如下示例:

    >>> L = [x * x for x in range(10)] 
    >>> L
    [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
    >>> g = (x * x for x in range(10)) 
    >>> g
    <generator object <genexpr> at 0x000001FBFD43A048>
    >>> list(g)
    [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
    

    由于生成器返回的结果是惰性序列,并不会直接返回想要结果,可以手动遍历,一个个进行打印:

    >>> g = (x * x for x in range(10))
    >>> next(g) 
    0
    >>> next(g)
    1
    >>> next(g)
    4
    >>> next(g)
    9
    >>> next(g)
    16
    >>> next(g)
    25
    >>> next(g)
    36
    >>> next(g)
    49
    >>> next(g)
    64
    >>> next(g)
    81
    >>> next(g)
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    StopIteration
    

    调用 next() 可以返回 g 的下一个元素值,当没有更多元素的时候,会抛出 StopIteration 的错误。若只是遍历获得结果,可以使用 for 循环,因为 generator 是可迭代对象:

    >>> g = (x * x for x in range(10))
    >>> for i in g: 
    ...     print(i) 
    ... 
    0
    1
    4
    9
    16
    25
    36
    49
    64
    81
    

    使用 for 循环遍历的时,就不需要担心 StopIteration 异常。

    还有另外一种方法可以创建生成器(generator),在 Python 中,使用 yield 的函数被称为生成器(generator)函数。使用 yield 实现斐波那契数列,如下示例:

    def fib(n):
        ct, a, b = 0, 0, 1
        while ct < n:
            yield b
            a, b = b, a + b
            ct += 1
        return "done"
    

    生成器和普通函数执行过程有所不同。函数是顺序执行,遇到 return 会返回结果。而生成器遇到 next() 会执行,遇到 yield 返回,再次执行会直接在上次返回的 yield 继续执行。如下示例:

    >>> def test():
    ...     print("value 1")
    ...     yield(1)
    ...     print("value 2")
    ...     yield(2)
    ...     print("value 3")
    ...     yield(3)
    ... 
    >>> t = test()
    >>> next(t)
    value 1
    1
    >>> next(t)
    value 2
    2
    >>> next(t)
    value 3
    3
    >>> next(t)
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    StopIteration
    

    上述代码中,调用 next() 后,打印 value 1,遇到 yield 输出 1,停止执行,再次执行 next() 时,在上次遇到 yield 语句停止的后面继续执行,输出 value 22,直到没有元素,抛出异常。这就是生成器函数的执行过程。

    迭代器


    开始迭代器的内容前,先延伸介绍一个可迭代对象的概念。可以直接作用于 for 循环的对象称为可迭代对象:Iterable 。可以用 isinstance() 进行判断:

    >>> from collections import Iterable
    >>> isinstance('abc', Iterable) 
    True
    >>> isinstance((x for x in range(10)), Iterable) 
    True
    >>> isinstance(100, Iterable)
    False
    

    可以被 next() 函数调用并不断返回下一个值得对象称为迭代器:Iterator。同样可以用 isinstance() 判断对象是否是 Iterator 对象:

    >>> from collections import Iterator 
    >>> isinstance('abc', Iterator)
    False
    >>> isinstance((x for x in range(10)), Iterator) 
    True
    

    可以看出,生成器也是 Iterator 对象。但 str 虽然是 Iterable,却不是 Iterator,同样的还有列表 list,字典 dict

    iter() 函数能够将 Iterable 变成 Iterator,例如:

    >>> isinstance(iter('abc'), Iterator) 
    True
    >>> isinstance(iter([]), Iterator)    
    True
    

    创建一个迭代器

    创建迭代器需要实现两个方法:__iter__()__next__()

    __iter__() 方法返回一个特殊的迭代器对象,这个对象能够实现 __next__() 方法通过 StopIteration 异常标识迭代的完成。

    __next__() 方法会返回下一个迭代器对象。

    实现逐步加 1 的类,示例如下:

    >>> class NumberIncrease(): 
    ...     def __iter__(self): 
    ...         self.x = 1      
    ...         return self     
    ...     def __next__(self): 
    ...         i = self.x      
    ...         self.x += 1
    ...         return i
    ... 
    >>> num_increase = NumberIncrease()
    >>> num_iter = iter(num_increase)
    >>> next(num_iter)
    1
    >>> next(num_iter)
    2
    >>> next(num_iter)
    3
    >>> next(num_iter)
    4
    >>> next(num_iter)
    5
    

    以上就是本篇的主要内容


    欢迎关注微信公众号《书所集录》

    相关文章

      网友评论

        本文标题:Python 生成器和迭代器

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