「进阶Python」第五讲:迭代器与生成器
更多精彩内容,请关注公众号【平凡而诗意】~
前言
迭代是Python中常用且非常强大的一个功能,它可以用于访问集合、列表、字符串、字典等数据结构的元素。我们经常使用循环和条件语句,我们也清楚哪些是可以迭代访问,但是具体它们之间有什么有什么异同之处?有哪些特点?什么是迭代器、什么是生成器、什么是可迭代对象?这些问题对于初学者而言却是很少去细致的研究,本文就来详细阐述一下它们之间的关系已经它们的特别之处。
可迭代对象
在讲解迭代器和生成器之前,先介绍一下可迭代对象。
可迭代对象是Python中一个非常庞大的概念,它主要包括如下三类:
- 迭代器
- 序列
- 字典
从上图可以看出不同概念之间的关系,迭代器是可迭代对象的一个子集,而生成器又是迭代器的一个子集,是一种特殊的迭代器。除了迭代器之外,Python中还有序列、字典等可迭代对象。
现在已经直观的了解了可迭代对象与迭代器、生成器之间的关系,那么用Python语言怎么表述它们的区别呢?
- 可迭代对象需要实现__iter__方法
- 迭代器不仅要实现__iter__方法,还需要实现__next__方法
在使用层面,可迭代对象可以通过in和not in访问对象中的元素,举一个例子,
X = set([1,2,3,4,5]) print(X) print(type(X)) print(1 in X) print(2 not in X) for x in X: print(x) # 输出 {1, 2, 3, 4, 5} <class 'set'> True False 1 2 3 4 5 前面提到,可迭代对象实现了__iter__方法,但是它没有实现__next__,这也是判定迭代器和其他可迭代对象的关键之处,可以看一下通过next访问上述示例中可迭代对象X会报错,
next(X) ? # 输出 TypeError: 'set' object is not an iterator
报的错误是'set' object is not an iterator,它指明了set集合是一个可迭代对象,但不是迭代器,下面就来介绍一下迭代器。
迭代器
迭代器是可迭代对象的一个子集,它是一个可以记住遍历的位置的对象,它与列表、元组、集合、字符串这些可迭代对象的区别就在于next方法的实现,其他列表、元组、集合、字符串这些可迭代对象可以很简单的转化成迭代器,通过Python内置的iter函数能够轻松把可迭代对象转化为迭代器,下面来看一个例子,
X = [1,2,3,4,5] print(type(X)) Y = iter(X) print(type(Y)) print(next(Y)) print(next(Y)) print(next(Y)) ? # 输出 <class 'list'> <class 'list_iterator'> 1 2 3
从上述示例中我们可以看出两点:
- 通过iter函数把list转化成了迭代器
- 可迭代器能够记住遍历位置,能够通过next方法不断从前往后访问
除了Python内置的iter之外,还可以通过Python内置的工具包itertools创建迭代器,其中函数包括,
- count
- cycle
- repeat
- accumulate
- chain
- compress
- dropwhile
- islice
- product
- permutations
- combinations
- ......
itertools中包含很多用于创建迭代器的实用方法,如果感兴趣嗯可以访问官方文档进行详细了解。
当然,也可以自己通过实现__iter__和__next__方法来定义迭代器,
class Iterator(object): def __init__(self, array): self.x = array self.index = 0 def __iter__(self): return self def __next__(self): if self.index < len(self.x): value = self.x[self.index] self.index += 1 else: raise StopIteration return value it = Iterator([1,2,3,4,5]) print(type(it)) for i in it: print(i) ? # 输出 <class '__main__.Iterator'> 1 2 3 4 5
生成器
从文章开头的流程图可以直观的看出,生成器是迭代器的子集,换句话说,生成器一定是迭代器,但是迭代器不全是生成器对象。
提及生成器就不得不提及一个Python中的关键字yiled,在Python中一个函数可以用yiled替代return返回值,这样的话这个函数就变成了一个生成器对象,举个例子对比一下,
def generator(array): for i in array: return i gen = generator([1,2,3,4,5]) print(type(gen)) ? # 输出 <class 'int'>
这是我们常见的return返回方式,这样的话generator函数获取的是一个int型对象,下面看一下换成yield关键字,
def generator(array): for i in array: yield(i) gen = generator([1,2,3,4,5]) print(type(gen)) ? # 输出 <class 'generator'>
这样的话获取的是一个生成器generator,除了yield之外,在Python3.3之后还加入了yield from获取生成器,允许一个生成器将其部分操作委派给另一个生成器,使得生成器的用法变得更加简洁,yield from后面需要加上可迭代对象,这样可以把可迭代对象变成生成器,当然,这里的可迭代对象不仅包含列表、元组,还包含迭代器、生成器。yield from相对于yield的有几个主要优点:
- 代码更加简洁
- 可以用于生成器嵌套
- 易于异常处理
下面就从简洁代码方面举个例子说明一下,
def generator(array): for sub_array in array: yield from sub_array ? gen = generator([(1,2,3), (4,5,6,7)]) ? # 输出 1 2 3 4 5 6 7
当我们需要访问多层/多维可迭代对象时,我们就不需要逐层的去用for ... in ...去访问,可以简单的通过yiled from把生成器委派给子生成器,除此之外还可以通过生成器表达式的方法得到生成式,后面会介绍。
print(next(gen)) print(next(gen)) ? # 输出 1 2
通过上面示例可以看出,生成器可以像迭代器那样使用iter和next方法。
读到这里可以会有疑惑,从这个示例看来生成器和迭代器并没有什么区别啊?为什么生成器还可以称得上是Python中的一大亮点?
首先它对比于迭代器在编码方面更加简洁,这是显而易见的,其次生成器运行速度更快,最后一点,也是需要着重说明的一点:节省内存。
也许在一些理论性实验、学术论文阶段可以不考虑这些工程化的问题,但是在公司做项目时,内存和资源占用是无法逃避的问题 。如果我们使用其他可迭代对象处理庞大的数据时,当创建或者返回值时会申请用于存储整个可迭代对象的内存,显然这是非常浪费的,因为有的元素当前我们用不到,也不会去访问,但它却一直占用这内存。这时候就体现了生成器的优点,它不是一次性把所有的结果都返回,而是当我们每读取一次,它会返回一个结果,当我们不读取时,它就是一个生成器表达式,几乎不占用内存。
生成器表达式
首先来看一个对比示例,
X = [1, 2, 3, 4, 5] it = [i for i in X] gen = (i for i in X) print(type(X)) print(type(it)) print(type(gen)) ? # 输出 <class 'list'> <class 'list'> <class 'generator'>
首先说一下it = [i for i in X],这种用法叫做列表生成式,在很多编程规范中非常推崇的一种替代for循环的方式,仔细看一下代码会发现,it = [i for i in X]与gen = (i for i in X)的区别非常小,只是一个用了中括号,一个用了小括号,但是它们的区别缺失非常大的,使用中括号的叫做列表生成式,获得的返回值是一个列表,而使用小括号叫做生成器表达式,获得的返回结果是一个生成器,这也是前面提到的,除了使用yield和yield from两个关键字外还可以使用生成器表达式获得生成器。
版权声明:
作者: FreeClashNode
链接: https://www.freeclashnode.com/news/article-2859.htm
来源: www.freeclashnode.com
文章版权归作者所有,未经允许请勿转载。
下一个:Java 如何读取网页内容
热门文章
- 11月2日免费节点分享|22.5M/S,V2ray节点/Clash节点/SSR节点/Singbox节点|免费上网梯子每天更新
- 10月14日免费节点分享|22.5M/S,Clash节点/V2ray节点/Singbox节点/SSR节点|免费上网梯子每天更新
- 10月11日免费节点分享|18.6M/S,V2ray节点/Clash节点/SSR节点/Singbox节点|免费上网梯子每天更新
- 10月13日免费节点分享|22.1M/S,V2ray节点/Clash节点/Singbox节点/Shadowrocket节点|免费上网梯子每天更新
- 10月25日免费节点分享|18.1M/S,SSR节点/V2ray节点/Singbox节点/Clash节点|免费上网梯子每天更新
- 10月12日免费节点分享|22.7M/S,Shadowrocket节点/V2ray节点/Singbox节点/Clash节点|免费上网梯子每天更新
- 10月10日免费节点分享|18.3M/S,V2ray节点/Singbox节点/Clash节点/SSR节点|免费上网梯子每天更新
- 10月27日免费节点分享|20M/S,Shadowrocket节点/Singbox节点/V2ray节点/Clash节点|免费上网梯子每天更新
- 10月28日免费节点分享|22.8M/S,Singbox节点/SSR节点/V2ray节点/Clash节点|免费上网梯子每天更新
- 10月21日免费节点分享|22M/S,Clash节点/Singbox节点/V2ray节点/SSR节点|免费上网梯子每天更新
最新文章
- 轻松翻越网络高墙:Shadowrocket一键导入配置全攻略
- 11月8日免费节点分享|21.3M/S,Clash节点/V2ray节点/Singbox节点/SSR节点|免费上网梯子每天更新
- 当Vmess突然失效:一场技术与封锁的无声博弈
- 11月7日免费节点分享|22.9M/S,Shadowrocket节点/V2ray节点/Singbox节点/Clash节点|免费上网梯子每天更新
- 梅林固件科学上网完全指南:从入门到精通,零成本解锁网络自由
- 11月6日免费节点分享|20.9M/S,Shadowrocket节点/V2ray节点/Singbox节点/Clash节点|免费上网梯子每天更新
- 幸运破解器科学上网全解析:解锁数字世界的终极指南
- 11月5日免费节点分享|21.9M/S,Shadowrocket节点/Singbox节点/V2ray节点/Clash节点|免费上网梯子每天更新
- 11月4日免费节点分享|18M/S,Clash节点/Singbox节点/SSR节点/V2ray节点|免费上网梯子每天更新
- 穿越数字迷雾:深度解析V2Ray中转迟滞之谜与极速优化指南
- 跨越数字边界:科学上网的终极指南与深度思考
- 从连接到掌控:深入理解 Quantumult 的工作流程与网络管理哲学
- 11月2日免费节点分享|22.5M/S,V2ray节点/Clash节点/SSR节点/Singbox节点|免费上网梯子每天更新
- 深度解析《荒野冲突》:征服与策略的终极对决
- 11月1日免费节点分享|20.3M/S,V2ray节点/Shadowrocket节点/Clash节点/Singbox节点|免费上网梯子每天更新
- 斐讯路由器刷机配置v2ray全攻略:打造安全高效的翻墙网络环境
- 10月31日免费节点分享|18.7M/S,Shadowrocket节点/Clash节点/V2ray节点/Singbox节点|免费上网梯子每天更新
- 谷歌浏览器科学上网扩展全攻略:从入门到精通
- 10月30日免费节点分享|20.4M/S,V2ray节点/SSR节点/Singbox节点/Clash节点|免费上网梯子每天更新
- 苹果手机V2Ray完全指南:从零开始打造安全上网环境
- 10月29日免费节点分享|21.6M/S,SSR节点/Clash节点/V2ray节点/Singbox节点|免费上网梯子每天更新
- 探索数字世界的门户:电脑科学上网贴吧完全指南
- 10月28日免费节点分享|22.8M/S,Singbox节点/SSR节点/V2ray节点/Clash节点|免费上网梯子每天更新
- 穿越数字边界:科学上网的全面指南与深度思考
- 10月27日免费节点分享|20M/S,Shadowrocket节点/Singbox节点/V2ray节点/Clash节点|免费上网梯子每天更新
- 数字世界的破壁之旅:科学上网全指南与实用工具深度解析
- 10月26日免费节点分享|21.5M/S,V2ray节点/SSR节点/Singbox节点/Clash节点|免费上网梯子每天更新
- 跨越知识边界:浙大学子的全球学术网络探索指南
- 10月25日免费节点分享|18.1M/S,SSR节点/V2ray节点/Singbox节点/Clash节点|免费上网梯子每天更新
- 10月24日免费节点分享|20.5M/S,V2ray节点/Clash节点/Singbox节点/Shadowrocket节点|免费上网梯子每天更新
- 刘大猫科学上网全攻略:解锁全球网络的终极指南
- 10月23日免费节点分享|22.2M/S,Shadowrocket节点/Clash节点/Singbox节点/V2ray节点|免费上网梯子每天更新
- 全面解析Quantumult安卓版:功能、安装与配置教程
- 双重防护,畅享无界:AdGuard联手V2RayNG,打造极致安全的上网体验
- 10月22日免费节点分享|18.8M/S,V2ray节点/SSR节点/Singbox节点/Clash节点|免费上网梯子每天更新
- 掌握Clash白名单设置:精准控制代理流量的艺术
- 10月21日免费节点分享|22M/S,Clash节点/Singbox节点/V2ray节点/SSR节点|免费上网梯子每天更新
- 突破网络边界:技术科学上网的终极安全指南
- 10月20日免费节点分享|22.9M/S,SSR节点/V2ray节点/Clash节点/Singbox节点|免费上网梯子每天更新
- Shadowrocket 选购指南:从入门到精通,找到你的专属代理神器
- 10月19日免费节点分享|19.3M/S,Singbox节点/V2ray节点/Clash节点/Shadowrocket节点|免费上网梯子每天更新
- 深入解读:V2Ray为何比SSR更安全?一场网络隐私的全方位较量
- 10月18日免费节点分享|20.6M/S,V2ray节点/Clash节点/SSR节点/Singbox节点|免费上网梯子每天更新
- 深度指南:Shadowrocket从入门到精通——iOS用户的网络自由密钥
- 10月17日免费节点分享|18M/S,Clash节点/SSR节点/V2ray节点/Singbox节点|免费上网梯子每天更新
- 深入解析科学上网套:全方位使用指南与常见问题解答
- 10月16日免费节点分享|22M/S,Shadowrocket节点/V2ray节点/Singbox节点/Clash节点|免费上网梯子每天更新
- 10月15日免费节点分享|21.2M/S,Clash节点/SSR节点/V2ray节点/Singbox节点|免费上网梯子每天更新
- 全局掌控:安卓设备上 Clash 全局模式完整设置指南与深度解析
- 解锁全球游戏体验:育碧平台科学上网全攻略与深度解析
归档
- 2026-11 15
- 2026-10 61
- 2026-09 58
- 2026-08 63
- 2026-07 61
- 2026-06 55
- 2026-05 56
- 2026-04 51
- 2026-03 60
- 2026-02 52
- 2026-01 56
- 2025-12 59
- 2025-11 55
- 2025-10 56
- 2025-09 55
- 2025-08 49
- 2025-07 31
- 2025-06 30
- 2025-05 31
- 2025-04 30
- 2025-03 388
- 2025-02 360
- 2025-01 403
- 2024-12 403
- 2024-11 390
- 2024-10 403
- 2024-09 388
- 2024-08 402
- 2024-07 427
- 2024-06 442
- 2024-05 181
- 2024-04 33
- 2024-03 31
- 2024-02 29
- 2024-01 51
- 2023-12 52
- 2023-11 32
- 2023-10 32
- 2023-09 3