前言
在Python中,可以使用列表生成式生成一个列表,但是列表生成式有一个缺点,就是如果要生成的列表中存在大量的元素而且又是按需使用的,显然对内存空间来说是极大的浪费,那现在能不能有一种思路是这样的:生成的列表中元素是可以按照某种算法推导,只是在需要下一个元素的时候,才去计算并且生成,这样做的好处是不必事先生成整个完整的list列表,大量节约内存空间。在python中,生成器就可以做到这一点。
生成器语法格式
1、同列表生成式一样,唯一区别是将“[]”换成“()”。如下所示:
说明:这种方式下,列表生成式和生成器作用是完全一样的,唯一的区别在于如果列表中元素数量过于巨大,使用列表生成式占用内存会大一点。
2、生成器函数(函数内部使用yield)
说明:如果在函数中出现了yield关键字,则这个函数不再是普通的函数,而是一个生成器,其实这个yield的含义就是将一个普通函数变成一个生成器。这种方式下,生成器可以实现无限制的列表元素,而列表生成式就无法做到这一点。
生成器的本质
生成器和列表生成式的不同之处在于,列表生成式其实就是一个list,而生成器并不是一个完整的列表,而是保存的是算法,是一种状态。也可以这么说,生成器的作用就是用来生成迭代器的。
案例a:第一种方式创建generator生成器
小总结:通过上面的案例可以看出,直接打印generator1时,并不是打印的列表,而是返回的是一个生成器对象。而且每调用next函数一次,就会从这个generator1生成器对象中计算下一个元素的值。
案例b:生成器函数
如果算法比较复杂,那么使用第一种方式就显的有点力不从心了,这个时候可以借助函数来去实现。
需求:模拟数据库主键自增。
思考:定义一个函数用来获取下一个自增的数据,默认从1开始。
代码实现:
小总结:生成器函数=函数+yield,但是此时的函数已经不再是一个普通函数,而是一个生成器。上图中的代码如何理解呢,我大致说下:第一次next时候,会执行生成器,执行到yield此行代码之后就直接返回结果了,当我下次再去执行next时候,程序就会接着从上一次的yield之后的代码继续执行。
总结
生成器generator的两种方式,对于列表生成式简单改造的方式来说,这种方式是比较简单,两者区别不大,而对于生成器函数来说,这种方式中函数不再是一个普通函数,生成器保存的是算法,而不是列表。实际上,我们通过for循环就可以实现对生成器的迭代,因为我们说生成器的作用其实就是用来生成迭代器的。