10分钟读懂python生成器

在python中,生成器在项目中的使用频率不可谓不高,可是对于刚接触python的开发者来讲,又是一个比较难懂的概念。本文将以一种简单易懂的方式来解释什么是python生成器。python

列表生成式 vs 生成器

列表生成式和生成器常常被拿来作比较,一个比较直观的对比是:bash

  • 列表生成式:[ ]是经过遍历可迭代对象生成一个list函数

  • 生成器:( )是直接返回可迭代对象ui

举个列表生成器的例子🌰:spa

[x+y for x in range(1,2) for y in range(1,3)] 
# result: [2,3,4,3,4,5]
复制代码

经过外层[ ]包裹内层的循环,从range(1,2)列表和range(1,3)中分别取出x和y做相加操做,返回一个列表生成式,直接得到列表结果:[2,3,4,3,4,5]。这就是一个列表生成器。code

在这里,咱们不妨让range(1,2)提高几个量级到到range(1,20000),让range(1,3)提高几个量级到到range(1,30000),再次计算结果就是一个容量为20000*30000的列表,占用了不少的存储空间。假如咱们须要获得列表的第1000个元素,那第1000个后面的元素就彻底不须要用到却占用空间,有点浪费。要是可以经过某种方式,不用计算所有的结果就能获得结果,那该多好了。cdn

因而咱们的生成器登场了。协程

将上面的[ ]改成( )就是生成器了☑️:对象

g = (x+y for x in range(1,2) for y in range(1,3)])
for i in g:
    print (i)
复制代码

咱们建立了一个名为g的generator后,而是经过for循环来迭代打印它(其内部是经过不停调用next( )方法每次迭代出一个数据)开发

生成器函数

生成器函数和普通函数在语法上几乎同样,可是生成器函数多了个yield关键字。若是一个函数定义中包含yield关键字,那么这个函数就再也不是一个普通函数,而是一个generator

def gen_list(n):
    for i in range(n):
      yield i ** 2
 
g = gen_list(4);
print(next(g));
print(next(g));
print(next(g));
# 结果
# 0
# 1
# 4
复制代码

这里经过yield语句一次返回一个结果并挂起当前状态,下次调用的时候会从当前状态继续。经过这种方式,对延迟操做提供了支持。所谓延迟操做,是指在须要的时候才产生结果,而不是当即产生结果。就像这个例子中,咱们每次调用next,每次只获得一个结果(依次是0、一、4...)

对比前面的经过列表生成式提升量级到range(1,20000)的例子来讲,这里的生成器由于一个一个结果计算,不须要计算所有列表,因此极大地节省了空间。同时,生成器使用经过yield状态挂起该生成器函数的状态,保留足够的信息,以便以后从它离开的地方继续执行,这就为咱们以后文章会分析到的协程的实现提供了简单的实现思路。

全栈公众号,感兴趣的小伙伴能够关注下

你的全栈助手
相关文章
相关标签/搜索