如果看此篇文章,再搞不懂可迭代对象、迭代器、生成器,我认为其他文章也不用看了。
首先看三个特殊方法(循环时自动调用)
- __iter__():返回一个迭代器对象。
- __next__():从容器中返回下一项。如果已经没有项可返回,则会引发 StopIteration 异常
- __getitem__:实现 self[key] 的求值。对于序列类型,接受的键应为整数和切片对象
一、可迭代对象:能够逐个返回成员的对象
可迭代对象大致包含以下种类
- 序列(如字符串、列表、元组等)
- 非序列(如集合、字典、文件对象等)
- 类对象 定义了__iter__()方法
- 类对象 定义了序列功能的__getitem__()方法
- 迭代器 定义了__iter__() 和 __next__() 方法
备注说明:
- 程序运行会先把 可迭代对象生成一个迭代器(iter(可迭代对象)),然后再进行一次性遍历
- 在使用可迭代对象时,通常情况不需要我们自己来生成迭代器(iter(可迭代对象))
- for循环或其他内置函数会自动生成一个迭代器进行遍历
使用情况:
- for in 循环
- enumerate()、zip()、map()、filter()等需要序列作为参数的地方
容器(序列、非序列)
类对象 __iter__()
类对象 __getitem__()
二、迭代器:表示一连串数据流对象,重复调用__next__()方法,逐个返回数据流中的成员
迭代器大概有两种类型
- 必须具有 __iter__() 方法,用来返回该迭代器对象自身。必须具有 __next__() 方法,从容器中返回下一项。
- 生成器 函数中有yield表达式
备注说明:
- 当没有数据可用时,则将引发 StopIteration 异常
- for循环或其他内置函数进行遍历取值时,会自动处理异常,正常结束遍历
迭代器自定义实现
三、生成器:实现迭代器的便捷方式。通过yield表达式实现
yield表达式不再详细介绍,详细了解yield运行方式,可点击【对照return讲解yield】文章
- 处理非常大的数据集合时,生成器非常有用
- yield表达式,只有定义生成器函数时,才会使用
- 生成器中的成员并不存在,使用一个成员立刻用yield生成一个成员(按需计算)
- 生成器很节省内存,因为是立刻生成的,所以耗费CPU进行计算
- 列表、字典等,成员是在内存中,使用时只是从内存中取出来,所以占用内存,不耗费CPU
生成器的两种形式:
- 1.生成器表达式:类似列表推导式
列表推导式详细可点击【列表推导式及演变姿势】
其句法与推导式相同,区别在于它是用圆括号而不是用方括号或花括号括起来
- 2.自定义生成器:通过yield来自己定义(包含3种模板)
- 2.1 yield value 配合next() 使用(典型生成器)
- 2.2 yield value 配合 for循环使用(常用生成器)
- 2.3 v=yield value 配合send(value)使用(协程函数)
关于协程以后讨论,协成的底层就是生成器
下面示例大家都称为 生产者消费者模型
强调一下 v=yield value 的执行方式:
先yield value返回value,暂停。生成器外面遇到send回到生成器执行n=value赋值,继续执行到yield value返回value后,再暂停