一、什么是生成器
通过列表生成式,我们可以直接创建一个列表。但是,受到内存限制,列表容量是有限的。而且,创建一个包含100万个元素的列表,不仅占用很大的存储空间,如果我们仅仅需要访问前面几个元素,那后面绝大多数元素占用的空间都白白浪费了。
所以,如果列表元素可以按照某种算法推算出来,那我们是否可以在循环的过程中不断推算出后续的元素呢?这样就不必创建完整的列表,从而节省大量的空间。在Python中,这种一边循环一边计算的机制,称为生成器:generator。
二、创建生成器
生成器表达式: 使用尖括号的列表推导式。
生成器函数: 使用yield的函数。
生成器函数yield的作用:
1
类似 return 返回值
2.暂停迭代,直到调用下一个next()方法
3.函数调用时返回生成器对象
生成器函数中返回值的send和next区别:
send可以传递参数作为yield表达式的值,而yield的参数是返回给调用者的值。比如函数中有一个yield赋值,x=yield 1,第一次迭代到这里会返回1,a还没有赋值。第二次迭代时使用.send(10),那么a=10。要注意的是第一次调用时必须是send(None)或者是next(),否则会报TypeError错误。总的来说next()等同于send(None)。示例:
三、生成器函数的几大特性
1、生成器函数包含一个或者多个yield
2、当调用生成器函数时,函数将返回一个对象,但是不会立刻向下执行
3、像__iter__()和__next__()方法等是自动实现的,所以我们可以通过next()方法对对象进行迭代
4、一旦函数被yield,函数会暂停,控制权返回调用者
5、局部变量和它们的状态会被保存,直到下一次调用
6、函数终止的时候,StopIteraion会被自动抛出
四、生成器、迭代器
迭代器持有一个内部状态的字段,用于记录下次迭代返回值,它实现了next和iter方法,迭代器不会一次性把所有元素加载到内存,而是需要的时候才生成返回结果。生成器一定是迭代器, 但是迭代器不一定是生成器。
五、为什么使用生成器
1、更容易使用,代码量较小
2、内存使用更加高效。比如列表是在建立的时候就分配所有的内存空间,而生成器仅仅是需要的时候才使用,更像一个记录
3、代表了一个无限的流。如果我们要读取并使用的内容远远超过内存,但是需要对所有的流中的内容进行处理,那么生成器是一个很好的选择,比如可以让生成器返回当前的处理状态,由于它可以保存状态,那么下一次直接处理即可。