一篇文章弄懂Python中的可迭代对象、迭代器和生成器


Posted in Python onAugust 12, 2019

我们都知道,序列可以迭代。但是,你知道为什么吗? 本文来探讨一下迭代背后的原理。

序列可以迭代的原因:iter 函数。解释器需要迭代对象 x 时,会自动调用 iter(x)。内置的 iter 函数有以下作用:

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

(2) 如果没有实现 iter 方法,但是实现了 getitem 方法,而且其参数是从零开始的索引,Python 会创建一个迭代器,尝试按顺序(从索引 0 开始)获取元素。

(3) 如果前面两步都失败,Python 抛出 TypeError 异常,通常会提示“C objectis not iterable”(C 对象不可迭代),其中 C 是目标对象所属的类。

由此我们可以明确知道什么是 可迭代的对象: 使用 iter 内置函数可以获取迭代器的对象。即要么对象实现了能返回迭代器的 iter 方法,要么对象实现了 getitem 方法,而且其参数是从零开始的索引。

下面看一个实现了getitem方法的例子:

一篇文章弄懂Python中的可迭代对象、迭代器和生成器

输出结果:

一篇文章弄懂Python中的可迭代对象、迭代器和生成器

我们创建了一个类Eg1,并且为这个类实现了 getitem 方法, 它的实例化对象o1 就是可迭代对象。

下面我们看一个实现 iter 方法的例子,因为用到了迭代器,所以在此我们必须在明确一下迭代器的用法。 标准的迭代器接口有两个方法:

一篇文章弄懂Python中的可迭代对象、迭代器和生成器

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

一篇文章弄懂Python中的可迭代对象、迭代器和生成器

返回 self,以便在应该使用可迭代对象的地方使用迭代器,例如在 for 循环中。

一篇文章弄懂Python中的可迭代对象、迭代器和生成器

我们创建了Eg2类,并为它实现了 iter 方法,此方法返回一个迭代器Eg2Iterator。 Eg2Iterator 实现了我们之前所说的next和iter方法。 实例化对象,并循环输出:

一篇文章弄懂Python中的可迭代对象、迭代器和生成器

可见,和o1是一样的。

我们通过两种方法实现了一个自己的可迭代对象,再此过程中我们要明确可迭代的对象和迭代器之间的关系:

Python 从可迭代的对象中获取迭代器。

iter方法从我们自己创建的迭代器类中获取迭代器,而getitem方法是python内部自动创建迭代器。

至此,我们明白了如何正确地实现可迭代对象,并且引出了怎样实现迭代器,但是使用迭代器方法(即上面的例子2)的代码量有点大,下面我们来了解一下如何使用更符合 Python 习惯的方式实现 Eg2类。

一篇文章弄懂Python中的可迭代对象、迭代器和生成器

哦了!就这么简单优雅!不用再单独定义一个迭代器类!

这里我们使用了yield 关键字, 只要 Python 函数的定义体中有 yield 关键字,该函数就是生成器函数。调用生成器函数时,会返回一个生成器对象。也就是说,生成器函数是生成器工厂。 当然,例子3的代码还可以使用yield from进一步简化:

一篇文章弄懂Python中的可迭代对象、迭代器和生成器

到这里我们明白了 可迭代对象 和 迭代器,还引申出了生成器,但还有一点没有提,那就是生成器表达式。

使用生成器表达式例子4的代码可以修改为:

一篇文章弄懂Python中的可迭代对象、迭代器和生成器

在python中,所有生成器都是迭代器。

最后,总结一下:

(1)什么是可迭代对象? 可迭代对象要么实现了能返回迭代器的 iter 方法,要么实现了 getitem 方法而且其参数是从零开始的索引。

(2)什么是迭代器? 迭代器是这样的对象:实现了无参数的 next 方法,返回下一个元素,如果没有元素了,那么抛出 StopIteration 异常;并且实现iter 方法,返回迭代器本身。

(3)什么是生成器? 生成器是带有 yield 关键字的函数。调用生成器函数时,会返回一个生成器对象。

(4)什么是生成器表达式? 生成器表达式是创建生成器的简洁句法,这样无需先定义函数再调用。

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,谢谢大家对三水点靠木的支持。

Python 相关文章推荐
Python中__init__和__new__的区别详解
Jul 09 Python
探索Python3.4中新引入的asyncio模块
Apr 08 Python
Python利用Beautiful Soup模块修改内容方法示例
Mar 27 Python
python批量实现Word文件转换为PDF文件
Mar 15 Python
python如何爬取个性签名
Jun 19 Python
Python中的异常处理try/except/finally/raise用法分析
Feb 28 Python
Python3.5文件读与写操作经典实例详解
May 01 Python
详解PANDAS 数据合并与重塑(join/merge篇)
Jul 09 Python
利用python实现PSO算法优化二元函数
Nov 13 Python
python实现在内存中读写str和二进制数据代码
Apr 24 Python
Python:__eq__和__str__函数的使用示例
Sep 26 Python
python 使用csv模块读写csv格式文件的示例
Dec 02 Python
Django认证系统实现的web页面实现代码
Aug 12 #Python
django 自定义过滤器(filter)处理较为复杂的变量方法
Aug 12 #Python
django-filter和普通查询的例子
Aug 12 #Python
利用python实现汉字转拼音的2种方法
Aug 12 #Python
python面向对象 反射原理解析
Aug 12 #Python
Python中正反斜杠(‘/’和‘\’)的意义与用法
Aug 12 #Python
Django 查询数据库并返回页面的例子
Aug 12 #Python
You might like
PHP 批量更新网页内容实现代码
2010/01/05 PHP
逆序二维数组插入一元素的php代码
2012/06/08 PHP
PHP实现的博客欢迎提示功能(很特别哦)
2014/06/05 PHP
php以post形式发送xml的方法
2014/11/04 PHP
php实现简单的语法高亮函数实例分析
2015/04/27 PHP
PHP在线调试执行的实现方法(附demo源码)
2016/04/28 PHP
PHP实现支付宝即时到账功能
2016/12/21 PHP
Laravel框架使用Seeder实现自动填充数据功能
2018/06/13 PHP
IE Firefox 使用自定义标签的区别
2009/10/15 Javascript
jquery遍历筛选数组的几种方法和遍历解析json对象
2013/12/13 Javascript
js 右侧浮动层效果实现代码(跟随滚动)
2015/11/22 Javascript
jquery form表单获取内容以及绑定数据
2016/02/24 Javascript
Boostrap实现的登录界面实例代码
2016/10/09 Javascript
jQuery插件版本冲突的处理方法分析
2017/01/16 Javascript
微信小程序表单验证错误提示效果
2017/05/19 Javascript
vue项目中使用particles实现粒子背景效果及遇到的坑(按钮没有点击响应)
2020/02/11 Javascript
python列表操作使用示例分享
2014/02/21 Python
Windows下PyMongo下载及安装教程
2015/04/27 Python
Python实现Sqlite将字段当做索引进行查询的方法
2016/07/21 Python
使用Python将数组的元素导出到变量中(unpacking)
2016/10/27 Python
TensorFlow实现随机训练和批量训练的方法
2018/04/28 Python
利用Python如何批量修改数据库执行Sql文件
2018/07/29 Python
python实现flappy bird小游戏
2018/12/24 Python
Python3内置模块random随机方法小结
2019/07/13 Python
python实现树的深度优先遍历与广度优先遍历详解
2019/10/26 Python
tensorflow求导和梯度计算实例
2020/01/23 Python
基于python3.7利用Motor来异步读写Mongodb提高效率(推荐)
2020/04/29 Python
python else语句在循环中的运用详解
2020/07/06 Python
安全生产中长期规划实施方案
2014/02/21 职场文书
篮球比赛策划方案
2014/06/05 职场文书
关于工作时间玩手机的检讨书
2014/09/18 职场文书
帝企鹅日记观后感
2015/06/10 职场文书
德能勤绩工作总结
2015/08/11 职场文书
数学备课组工作总结
2015/08/12 职场文书
爱国主义教育主题班会
2015/08/13 职场文书
Java 数据结构七大排序使用分析
2022/04/02 Java/Android