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

可迭代对象、迭代器和生成器

作者: 凹凸曼_ebb9 | 来源:发表于2018-04-21 00:08 被阅读0次

    迭代是数据处理的基石。扫描内存中放不下的数据时,我们要找到一种惰性获取数据项的方式,即按需一次获取一个数据项,这就是迭代器模式。

    在python语言内部,迭代器用于支持:

    for 循环

    构建和扩展集合类型

    逐行遍历文本文件

    列表推导、字典推导和集合推导

    元组拆包

    调用函数时,使用*拆包实参

    序列可迭代的原因:iter函数

    解释器需要迭代对象x时,会自动调用iter(x)

    内置的iter函数由以下作用。

    1、检查对象是否实现了__iter__方法,如果实现了就调用它,获取一个迭代器。

    2、如果没有实现__iter__方法,但是实现了__getitem__方法,python会创建一个迭代器,尝试按顺序获取元素。

    3、如果尝试失败,python抛出TypeError异常,通常会提示“C object is not iterable”

    可迭代的对象与迭代器的对比

    可迭代的对象:

    使用iter内置函数可以获取迭代器的对象。如果对象实现了能返回迭代器的__iter__方法,那么对象就是可迭代的。序列都可以迭代,因为实现了__getitem__方法。

    标准迭代器接口有两个方法:

    __next__:返回下一个可用的元素,如果没有元素了,则抛出StopIteration异常。

    __iter__:返回self,以便在应该可迭代对象的地方使用迭代器。

    迭代器:

    迭代器时这样的对象:实现了无参数的__next__方法,返回序列中的下一个元素,如果没有元素了,那么抛出StopIteration异常。python中的迭代器还实现了__iter__方法,因此迭代器也可以迭代。

    典型的迭代器

    下例中定义的Sentence类可以迭代,因为它实现了特殊的__iter__方法,构建并返回一个SentenceIterator实例。

    把Sentence变成迭代器:坏主意

    可迭代的对象有个__iter__方法,每次实例化一个新的迭代器,而迭代器要实现__next__方法,返回单个元素,此外还要实现__iter__方法,返回迭代器本身,因此,迭代器可以迭代,但是可迭代对象不是迭代器。

    可迭代的对象一定不能是自身的迭代器。也就是说,可迭代的对象必须实现__iter__方法,但不能实现__next__方法。

    生成器函数

    实现相同功能,但更符合python习惯的方式是,用生成器函数代替SentenceIterator类。

    在上例中,迭代器其实是生成器对象,每次调用__iter__方法都会自动创建,因为这里的__iter__方法是生成器函数。

    生成器函数的工作原理

    只要python函数的定义体中有yield关键字,该函数就是生成器函数。调用生成器函数时,会返回一个生成器对象,也就是说,生成器函数是生成器工厂。

    惰性实现

    之前实现的几版Sentence类都不具有惰性,因为__init__方法急迫地构建好了文本中的单词列表,然后将其绑定到self.words属性上。这样就得处理整个文本,列表使用的内存量可能与文本本身一样多。

    re.finditer函数是re.findall函数的惰性版本,返回的不是列表,而是一个生成器。

    生成器表达式

    生成器表达式可以理解为列表推导的惰性版本:不会迫切地构建列表,而是返回一个生成器,按需惰性生成元素。也就是说,如果列表推导是制造列表的工厂,那么生成器表达式就是制造生成器的工厂。

    下例先在列表推导中使用gen_AB生成器函数,然后在生成器表达式中使用

    下例用生成器表达式实现Sentence类

    相关文章

      网友评论

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

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