一篇文章弄懂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中列表元素连接方法join用法实例
Apr 07 Python
编写Python爬虫抓取暴走漫画上gif图片的实例分享
Apr 20 Python
详解supervisor使用教程
Nov 21 Python
python获取网页中所有图片并筛选指定分辨率的方法
Mar 31 Python
Pandas读取MySQL数据到DataFrame的方法
Jul 25 Python
Django压缩静态文件的实现方法详析
Aug 26 Python
Python 从列表中取值和取索引的方法
Dec 25 Python
Python一个简单的通信程序(客户端 服务器)
Mar 06 Python
在Pytorch中计算卷积方法的区别详解(conv2d的区别)
Jan 03 Python
详解python tkinter模块安装过程
Jan 06 Python
Python pandas求方差和标准差的方法实例
Aug 04 Python
python playwright之元素定位示例详解
Jul 23 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
PHP4之真OO
2006/10/09 PHP
PHP中操作ini配置文件的方法
2013/04/25 PHP
php ckeditor上传图片文件名乱码解决方法
2013/11/15 PHP
基于jquery实现的一个选择中国大学的弹框 (数据、步骤、代码)
2012/07/26 Javascript
javascript实现选中复选框后相关输入框变灰不可用的方法
2015/08/11 Javascript
使用JS读取XML文件的方法
2016/11/25 Javascript
JavaScript代码实现txt文件的上传预览功能
2018/03/27 Javascript
微信小程序网络封装(简单高效)
2018/08/06 Javascript
vue项目使用微信公众号支付总结及遇到的坑
2018/10/23 Javascript
vue 实现搜索的结果页面支持全选与取消全选功能
2019/05/10 Javascript
微信小程序仿淘宝热搜词在搜索框中轮播功能
2020/01/21 Javascript
js实现烟花特效
2020/03/02 Javascript
Vue项目中使用flow做类型检测的方法
2020/03/18 Javascript
[01:45]2014DOTA2 TI预选赛预选赛 战前探营!
2014/05/21 DOTA
[02:04]2014DOTA2国际邀请赛 DK一个时代的落幕
2014/07/21 DOTA
python实现快速排序的示例(二分法思想)
2018/03/12 Python
Python实现读取txt文件中的数据并绘制出图形操作示例
2019/02/26 Python
在Pycharm中使用GitHub的方法步骤
2019/06/13 Python
python实现按首字母分类查找功能
2019/10/31 Python
python图片指定区域替换img.paste函数的使用
2020/04/09 Python
如何在python中执行另一个py文件
2020/04/30 Python
Pytorch转keras的有效方法,以FlowNet为例讲解
2020/05/26 Python
如何基于Python pygame实现动画跑马灯
2020/11/18 Python
用Python实现童年贪吃蛇小游戏功能的实例代码
2020/12/07 Python
html5记忆翻牌游戏实现思路及代码
2013/07/25 HTML / CSS
新西兰领先的鞋类和靴子网上商城:Merchant 1948
2017/09/08 全球购物
AJAX检测用户名是否存在的方法
2021/03/24 Javascript
青春奉献演讲稿
2014/05/08 职场文书
询价采购方案
2014/06/09 职场文书
广播体操口号
2014/06/18 职场文书
英语系毕业生求职信
2014/07/13 职场文书
2014年销售助理工作总结
2014/12/01 职场文书
介绍信格式
2015/01/30 职场文书
Nginx+SpringBoot实现负载均衡的示例
2021/03/31 Servers
Python中threading库实现线程锁与释放锁
2021/05/17 Python
简单聊聊Golang中defer预计算参数
2022/03/25 Golang