在python中,生成器在项目中的使用频率不可谓不高,但是对于刚接触python的开发者来说,又是一个比较难懂的概念。本文将以一种简单易懂的方式来解释什么是python生成器。
1. 列表生成式 vs 生成器
欢迎大家加入小编创建的Python行业交流群,有大牛答疑,有资源共享,有企业招人!是一个非常不错的交流基地!群号:683380553
列表生成式和生成器经常被拿来做比较,一个比较直观的对比是:
列表生成式:[ ]是通过遍历可迭代对象生成一个list
生成器:( )是直接返回可迭代对象
举个列表生成器的例子🌰:
1[x+yforxinrange(1,2)foryinrange(1,3)]
2# result: [2,3,4,3,4,5]
通过外层[ ]包裹内层的循环,从range(1,2)列表和range(1,3)中分别取出x和y作相加操作,返回一个列表生成式,直接获得列表结果:[2,3,4,3,4,5]。这就是一个列表生成器。
在这里,我们不妨让range(1,2)提升几个量级到到range(1,20000),让range(1,3)提升几个量级到到range(1,30000),再次计算结果就是一个容量为20000*30000的列表,占用了很多的存储空间。假如我们需要得到列表的第1000个元素,那第1000个后面的元素就完全不需要用到却占用空间,有点浪费。要是能够通过某种方式,不用计算全部的结果就能得到结果,那该多好了。
于是我们的生成器登场了。
将上面的[ ]改为( )就是生成器了☑️:
1g = (x+yforxinrange(1,2)foryinrange(1,3)])
2foriing:
3print(i)
我们创建了一个名为g的generator后,而是通过for循环来迭代打印它(其内部是通过不停调用next( )方法每次迭代出一个数据)
2. 生成器函数
生成器函数和普通函数在语法上几乎一样,但是生成器函数多了个yield关键字。如果一个函数定义中包含yield关键字,那么这个函数就不再是一个普通函数,而是一个generator
1defgen_list(n):
2foriinrange(n):
3yieldi **2
4
5g = gen_list(4);
6print(next(g));
7print(next(g));
8print(next(g));
9# 结果
10# 0
11# 1
12# 4
这里通过yield语句一次返回一个结果并挂起当前状态,下次调用的时候会从当前状态继续。通过这种方式,对延迟操作提供了支持。所谓延迟操作,是指在需要的时候才产生结果,而不是立即产生结果。就像这个例子中,我们每次调用next,每次只得到一个结果(依次是0、1、4...)
对比前面的通过列表生成式提高量级到range(1,20000)的例子来说,这里的生成器因为一个一个结果计算,不需要计算全部列表,所以极大地节省了空间。同时,生成器使用通过yield状态挂起该生成器函数的状态,保留足够的信息,以便之后从它离开的地方继续执行,这就为我们之后文章会分析到的协程的实现提供了简单的实现思路。
网友评论