为什么要有生成器
生成器 Generator,这个名字听起来就有点怪怪的。一种程序语言当中,为什么要有生成器这样的东西?它是为了解决什么问题而存在的呢?
为什么有生成器¶
你要了解生成器,首先你必须知道循环这回事。因为循环是一个用简短语句表示的重复执行过程。 那么生成器就是为循环设计的。
那么是因为循环遇到了什么问题,才会有人想要要用生成器呢? 在循环的时候,我们的目的是为了每次循环拿到一些特定数据,然后为这些数据做处理。但是无可避免的会在内存中记录这些数值, 当需要记录的数值很多的时候,我们的内存可能就吃不消了。而生成器,即现做现吃的意思,你跟着我的教程,往下走, 就会越来越深刻体会到 Python 是怎么现做现吃
了~
拿到合适的才进入下一轮¶
这种需要先保存一个 items
的列表,但当你做机器学习或者数据处理的时候, 如果这个 items
列表的数据量很大,就会非常占内存。所以生成器的一个重要目的就是避免在内存中记录这样的一个大数据,避免把内存撑爆。
所以生成器这个名字也比较应景,我只在需要这个数据的时候生成它,生成完了我就不用了,也不需要记录。这种时候将会节约我很多内存的需求。 我们用生成器的 yield
方式,重新定义一下上面的功能。
我能在主循环里拿到什么,其实是由 need_return
生成器决定的。所以 need_return
可以是一个很复杂的功能。 比如下面这个,我往外扔什么数字,是取决于我内部的一个特殊运算的。
自定义生成器的初始化¶
生成器是一个 function, 所以它能做 function 能做的事情,比如传参。 这就大大提升了循环能有的情况,我居然能控制循环的初始化状态了。在下面这个例子中,你看看如果你在 need_return(10)
中传入不同的值,会怎么影响主循环的结果输出的?
定义生成器类¶
用一个 class 也是可以表示一个迭代器,生成器的。 如果我们将上面的逻辑转化成 class
,这个 class 可能相对比较复杂,但是也意味着你可以有更多设置和控制发生在这个 class 里面。 里面我们申明了用于生成器的两个 method,__iter__
和 __next__
。
__iter__
的意思是,当我在外面 for 循环进行迭代时,我返回什么?在下面例子中,我就把自己这个 class 本身返回回去,继续让自己做迭代就好了。
__next__
的意思是每次迭代的时候,我的函数会放出来什么元素。下面的功能中实现的就是放出来一个被计算过的 item 元素。
总结¶
其实生成器并没有很复杂。只要你找到的使用生成器的场景,生成器在节省内存方面还是很有贡献的。如果当你的循环内存不足时,或者运行很慢时,生成器是你需要考虑的。