python可迭代对象、迭代器、生成器
目录
- 迭代器模式
- 迭代器模式与yield关键字
- python迭代器功能
- 序列可以迭代的原因---iter函数
- 可迭代对象与迭代器
- 可迭代对象
- 可迭代对象生成迭代器
- 迭代器
- 可迭代对象与迭代器对应的抽象基类
- 迭代器定义
- 不要把可迭代对象变成自身的迭代器
- 生成器函数
- 生成器函数定义
- 生成器函数示例
- 生成器函数内部工作机制
- 生成器函数与return语句
- 生成器表达式
- 标准库中的生成器函数
- 用于过滤的生成器函数
- 用于映射的生成器函数
- 用于合并的生成器函数
- 用于扩展输入的可迭代对象的生成器函数
- 用于重新排列元素的生成器函数
- python3.3新句法:yield from
- 可迭代的规约函数
- iter函数深入分析
迭代器模式
迭代器模式与yield关键字
- 扫描内存中放不下的数据集时,需要惰性获取数据,即按需一次获取一个数据项,这就是迭代器模式。
- python为了实现迭代器模式,加入了yield关键字,用于构建生成器。
- 所有生成器都是迭代器,因此生成器完全实现了迭代器接口。
- 一般认为,迭代器用于从一个集合中取出元素,生成器则用于凭空生成元素,但在python中,一般将其视作同一概念。
- python3中,即使时内置的range()函数也返回一个生成器对象,而在以前则返回完整的列表。
- python中所有集合都是可迭代的。
python迭代器功能
- for循环
- 构建和扩展集合类型
- 逐行遍历文本文件
- 列表推导、字典推导和集合推导,本质还是for循环
- 元组拆包
- 调用函数时,使用 * 拆包实参
序列可以迭代的原因---iter函数
- 解释器需要迭代对象x时,会自动调用iter(x):
- 首先检查对象是否实现了__iter__方法,如果有,则调用它并返回一个迭代器。
- 如果没有实现__iter__方法,但是实现了__getitem__方法,python会创建一个迭代器,尝试按索引顺序获取元素。
- 若尝试失败,python抛出TypeError异常,提示 \(\times\times\times\) object is not iterable。
- 任何序列均可迭代,是因为任何序列都要实现__getitem__方法。
- 可以使用 isinstance(x, abc.Iterable)来判断对象x是否可迭代,但这种方式不准确,因为不会考虑__getitem__方法的存在。最好还是用iter(x)来判断,如果不抛出异常则可迭代。
可迭代对象与迭代器
可迭代对象
- 使用内置函数iter可以获取迭代器的对象。如果对象实现了__iter__方法,则该对象是可迭代的。序列都是可迭代的。
可迭代对象生成迭代器
- 调用iter方法,传入一个可迭代对象,生成一个迭代器。
- 调用next(it)方法,传入迭代器,每次迭代一个元素。
- 当迭代器中元素耗尽,则抛出StopIteration异常。
- 废弃迭代器对象。
- 这里是显示处理的StopIteration异常,python语言内部会自动处理for循环和其它迭代上下文中的StopIteration异常。
迭代器
- 标准迭代器接口有两个方法
- next,返回下一个可用的元素,若没有元素了,则抛出StopIteration异常。
- iter,返回self,以便在该使用可迭代对象的时候使用迭代器,比如for循环中。
可迭代对象与迭代器对应的抽象基类
- gen_123是生成器函数,因为函数体中包含关键字yield。
- 生成器函数每次执行到yield就生成一个元素,因此生成器函数体中一般有循环,但是也可以没有,比如这里直接列出了三个yield语句用于三次生成。
- gen_123属于function类。
- 调用gen_123返回一个生成器对象。
- 生成器是迭代器,每次迭代都生成yield表达式生成的值。
- g是生成器对象。
- 生成器都是迭代器,可以调用next(g)获取下一个生成的元素。
- 生成器对象中元素耗尽后,抛出StopIteration异常。
生成器函数内部工作机制
- 调用生成器函数会生成一个生成器对象,包裹生成器函数的定义体。
- 把生成器对象传给next函数时,生成器函数向前执行,直到遇到第一个yield表达式,然后返回产出的值,并在当前位置暂停。
- 若元素未耗尽,继续执行,直到再次遇到yield表达式。
- 若元素耗尽,抛出StopIteration异常。
生成器函数与return语句
- 生成器函数体中的return语句会触发生成器对象抛出StopIteration异常。
- python3.3之前生成器函数体中不能有return语句。
- 只有把生成器函数当作协程使用时,return语句才有意义。
生成器表达式
- 生成器表达式是语法糖,完全可以替换成生成器函数,只是有时候生成器表达式更方便。
标准库中的生成器函数
用于过滤的生成器函数
用于映射的生成器函数
用于合并的生成器函数
用于扩展输入的可迭代对象的生成器函数
用于重新排列元素的生成器函数
python3.3新句法:yield from
-
在chain生成器函数中,可迭代对象iterables中的元素it也是可迭代对象。
-
对it用for循环和yield表达式来创建一个生成器,每次生成一个元素i。
-
用yield from句法可以取代内层循环:
-
使用yield from 后加上可迭代对象,可把可迭代对象中的元素一个一个yield出来,对比yield来说代码更简洁,不再使用循环来yield元素。
-
yield from并不是语法糖,其会创建通道,把内层生成器直接与外层客户端联系起来。把生成器当成协程使用时,此通道特别重要,不仅能为客户端代码生成器,还能使用客户端代码提供的值。
可迭代的规约函数
- 归约函数都接收一个可迭代的对象,然后返回单个结果。
- sorted函数
内置函数sorted可以接收任意可迭代对象,且会构建并返回真正的列表,因此要读取可迭代对象中的每个元素才能排序,sorted不是生成器函数。
iter函数深入分析
- iter函数可以使用任意可调用对象创建迭代器。需要传入两个参数,第一个参数是可调用对象,第二个参数是哨兵。不断调用第一个对象产出值,直到产出了哨兵就抛出异常。