资讯专栏INFORMATION COLUMN

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

starsfun / 330人阅读

摘要:本文重点掌握可迭代的对象的定义掌握可迭代对象迭代器与生成器之间的关系和异同熟悉标准库中生成器。二迭代器迭代器介绍迭代器用于从集合中取出元素的对象。若想再次迭代须重建迭代器。迭代器检查方式调用,。区别可迭代的对象不是迭代器。

导语:本文章记录了本人在学习Python基础之控制流程篇的重点知识及个人心得,打算入门Python的朋友们可以来一起学习并交流。

本文重点:

1、掌握可迭代的对象的定义;
2、掌握可迭代对象、迭代器与生成器之间的关系和异同;
3、熟悉标准库中生成器。
一、可迭代的对象

可迭代的对象:使用iter内置函数可以获取迭代器的对象。如果对象实现了能返回迭代器的__iter__方法,那么对象就是可迭代的。如果没有实现__iter__而实现了__getitem__方法,并且其参数是从零开始的索引,这种对象如序列也是可迭代的。
向后兼容:之所以任何Python序列可迭代是为了向后兼容。

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

若对象实现了__iter__方法,获取一个迭代器;

若对象没实现__iter__方法,但实现了__getitem__方法,Python会创建一个迭代器,尝试从索引0开始获取元素;

若尝试失败,Python抛出TypeError。

标准的序列都实现了__iter__方法,这是鸭子类型的极端形式。
在白鹅类型中,只要对象实现了__iter__方法,那么它就是可迭代的对象。

注意:
(1)只有实现了__iter__方法的对象能通过子类测试issubclass(Object,abc.Iterator)
(2)检查对象能否迭代最准确的方法是调用iter(x)函数,如果不可迭代再处理TypeError。因为iter(x)会考虑到实现__getitem__方法的部分可迭代对象。

二、迭代器 1、迭代器介绍

迭代器:用于从集合中取出元素的对象。
迭代器的功能:用于支持下列操作

for循环

构建和扩展集合类型

逐行遍历文本文件

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

元组拆包

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

迭代器的接口协议

__next__,返回下一个可用的元素。当没有元素时抛出StopIteration异常。

__iter__,返回self,即迭代器本身。


迭代器特点:

可迭代。由于Python中的迭代器实现了__iter__方法,因此也可以迭代。

易耗损。迭代器经过一次逐次取值的循环后便耗尽了。若想再次迭代须重建迭代器。

迭代器检查方式:调用isinstance(object,abc.Iterator)。
检查原理:归结于Iterator.__subclasshook__方法。无论对象所属的类是Iterator的真实子类还是虚拟子类,都能够检查。

2、迭代器和可迭代对象之辨析:

联系:Python从可迭代的对象中获取迭代器

区别:可迭代的对象不是迭代器

3、迭代器模式

迭代器模式:按需一次获取一个数据项。
扫描内存中放不下的数据集时,我们要找到一种惰性获取数据项的方式,即按需一次获取一个数据项。这就是迭代器模式(Iterator pattern) 。
迭代器模式的用途:

访问一个聚合对象的内容而无需暴露它的内部表示

支持对聚合对象的多种遍历

为遍历不同的聚合结构提供一个统一的接口(即支持多态迭代)

4、迭代器模式实例

下面构造一个可以处理文本匹配并迭代的实例:

import reprlib
import re

reword=re.compile("w+")
#第一版:迭代器模式
class Sentence:
    def __init__(self,text):
        self.text=text
        self.words=reword.findall(text)
    def __repr__(self):
        return "Sentence({})".format(reprlib.repr(self.text))
    def __iter__(self):
        return SentenceIterator(self.words)
class SentenceIterator:
    def __init__(self,text):
        self.words=text
        self.index=0
    def __next__(self):
        try:
            word=self.words[self.index]

        except IndexError:
            raise StopIteration()
        self.index += 1
        return word
    def __iter__(self):
        return self
title=Sentence("We have a dream!")
print(title)
for i in title:
    print(i)
输出:
Sentence("We have a dream!")
We
have
a
dream

注意:
(1)不要把迭代器接口应用到可迭代对象上,这是常见的反模式
(2)可迭代对象必须实现__iter__方法,但不能实现__next__方法

三、生成器 1、生成器相关概念介绍

生成器:用于按需生成元素的对象。在Python社区中大多数时候都把迭代器和生成器视作同一概念。

生成器函数:拥有yield关键字的Python函数。
生成器表达式:制造生成器的工厂,支持惰性产值。
生成器工厂函数:返回生成器的函数,定义体中可以没有yield关键字。

生成器函数与生成器表达式优点比较:

生成器函数:使用重复使用的情景,也可以作为协程使用。

生成器表达式:代码简洁易读。

Tips:生成器表达式作为单参数传入时无须写一对括号,而多参数时须将小括号加上。

2、生成器函数工作原理

实例1:通过一个问候同学的代码来了解生成器函数是如何工作的

def gen():
    print("start")
    yield "Jack"
    print("continue")
    yield "Dennis"
    print("end")
for i in gen():
    print("Hello ",i)
输出:
start
Hello  Jack
continue
Hello  Dennis
end

原理分析:不难发现,for循环中操作的对象是生成器中的yield生成的值。原因在于,生成器是迭代器,会生成传给yield关键字的表达式的值。
注意:不管有没有return语句,生成器函数都不会抛出StopIteration异常,而是在生成全部值之后直接退出。

实例2:生成器函数改进版

import reprlib
import re

reword=re.compile("w+")
#第二版:生成器函数
class Sentence:
    def __init__(self,text):
        self.text=text
        self.words=reword.findall(text)
    def __repr__(self):
        return "Sentence({})".format(reprlib.repr(self.text))
    def __iter__(self):
        for i in self.words:
            yield i
        return
title=Sentence("We have a dream!")
print(title)
for i in title:
    print(i)
3、惰性产值:生成器表达式模式改进版
import reprlib
import re

reword=re.compile("w+")
#第三版:生成器表达式
class Sentence:
    def __init__(self,text):
        self.text=text
    def __repr__(self):
        return "Sentence({})".format(reprlib.repr(self.text))
    def __iter__(self):
        return (match.group() for match in reword.finditer(self.text))
title=Sentence("We have a dream!")
print(title)
for i in title:
    print(i)

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

四、标准库中有用的生成器 1、五大类生成器

用于过滤的生成器函数: itertools.takewhile/compress/dropwhile/filter/filterfalse/islice/

用于映射的生成器函数: 内置的 enumerate/map itertools.accumulate/starmap

用于合并的生成器函数:itertools.chain/from_iterable/product/zip_longest/ 内置的 zip

从一个元素产生多个值,扩展输入的可迭代对象: itertools.combinations/combinations_with_replacement/count/cycle/permutations/repeat

产出输入可迭代对象的全部元素,以某种方式排列:itertools.groupby/tee/ 内置的 reversed

五、其它

1、归约函数:接受可迭代对象并返回单个结果的函数。

这里的all和any函数会短路,即一旦得出结果马上停止迭代。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/44563.html

相关文章

  • 流畅python读书笔记-第十四章-可迭代对象迭代器和成器

    摘要:可迭代的对象迭代器和生成器理念迭代是数据处理的基石。可迭代的对象与迭代器的对比从可迭代的对象中获取迭代器标准的迭代器接口有两个方法。此外,也没有办法还原迭代器。最终,函数的定义体返回时,外层的生成器对象会抛出异常这一点与迭代器协议一致。 可迭代的对象、迭代器和生成器 理念 迭代是数据处理的基石。扫描内存中放不下的数据集时,我们要找到一种惰性获取数据项的方式,即按需一次获取一个数据项。这...

    kohoh_ 评论0 收藏0
  • python奇遇记:迭代器和成器

    摘要:来说说迭代器和生成器,还有可迭代对象和生成器表达式。有点绕是不是,其实,一般只要知道可迭代对象以及它是如何实现的就行了,中常常用生成器来代替迭代器,可以说,生成器就是迭代器。 来说说迭代器和生成器,还有可迭代对象和生成器表达式。 之前简单的提到过,一个对象是可迭代的可以理解为能够使用for循环。这样说其实不太准确,某个对象可迭代是因为它内部实现了$__iter__$这个特殊方法。比如在...

    atinosun 评论0 收藏0
  • python迭代器资料整理

    摘要:满足以上要求的对象,就是迭代器。其中,必需返回一个迭代器对象,则负责迭代逻辑并在迭代完毕时触发异常。可以在遍历迭代器的时候,加入一个判断语句,避免无法多次迭代的情况发生参考资料官网迭代器文档 什么是迭代器 相关概念定义 迭代器(Iterator): 满足迭代协议的对象就是迭代器 iterator就是实现了Iteration Protocol的对象,这类对象都支持循环遍历的操作(for...

    Muninn 评论0 收藏0
  • Python基础-迭代器和成器

    摘要:迭代器迭代器用于循环构建和扩展集合类型逐行遍历文本文件列表推导字典推导和集合推导元组拆包调用函数时,使用拆包实参解释器需要迭代对象时,会自动调用内置的函数,有以下功能检查对象是否实现了方法,如果实现了就调用它,获取一个迭代器。 迭代器 迭代器用于: for 循环 构建和扩展集合类型 逐行遍历文本文件 列表推导、 字典推导和集合推导 元组拆包 调用函数时, 使用 * 拆包实参 解释器...

    objc94 评论0 收藏0
  • Python 进阶之路 (九) 再立Flag, 社区最全itertools深度解析(上)

    摘要:例如,以下对两个的相应元素求和这个例子很好的解释了如何构建中所谓的迭代器代数的函数的含义。为简单起见,假设输入的长度可被整除。接受两个参数一个可迭代的正整数最终会在中个元素的所有组合的元组上产生一个迭代器。 前言 大家好,今天想和大家分享一下我的itertools学习体验及心得,itertools是一个Python的自带库,内含多种非常实用的方法,我简单学习了一下,发现可以大大提升工作...

    tuantuan 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<