Python强大的引进-生成器。这就是我们今天要学习的这一章内容。
定义:
在Python中,这种一边循环一边计算的机制,称为生成器(Generator)。换句更简单的话来理解:任何包含yield语句的函数称为为生成器。
好处:
通过列表生成式,我们可以直接创建一个列表。但是,受到内存限制,列表容量肯定是有限的。而且,创建一个包含100万个元素的列表,不仅占用很大的存储空间,如果我们仅仅需要访问前面几个元素,那后面绝大多数元素占用的空间都白白浪费了。
所以,如果列表元素可以按照某种算法推算出来,那我们是否可以在循环的过程中不断推算出后续的元素呢?这样就不必创建完整的list,从而节省大量的空间。
工作原理:
它是在for循环的过程中不断计算出下一个元素,并在适当的条件结束for循环。对于函数改成的generator来说,遇到return语句或者执行到函数体最后一行语句,就是结束generator的指令,for循环随之结束。
如何创建:
1. 只要把一个列表生成式的【】换成()就可以。
2. 上图的例子是用yield来说明一下怎么创建生成器。
打开百度App,看更多图片
其实与创建函数类似: 区别是,创建函数是return返回值。创建生长期是yield产生多个值,每次产生一个,函数就会冻结,等在那里等待被再次激活。等激活后从停止的那点开始执行。
生成器种类:
A. 循环生成器。与列表推导式类似。只不过一个是返回列表一个是返回生成器(不会立刻循环)。请看下面例子来说明区别。
>>> L = [x * x for x in range(10)]
>>> L [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
>>> g = (x * x for x in range(10))
>>> g <generator object <genexpr> at 0x104feab40>
>>> for n in g:
print n
B. 递归生成器。
C. 通用生成器:
生成器的组成 1. 生成器函数: def定义,包含yield部分。
2. 生成器迭代器:这个函数的返回部分。
生成器方法
send
类似于next,在比不过需要一个发送的参数。
def repeater(value):
while True:
new=(yield value)
if new is not None:value=new
>>> r=repeater(42)
>>> r.next()
42
>>> r.send('hello world')
'hello world'
throw方法:
使用异常类型调用,还有可选的值以及回溯对象,用于生成器内引发一个异常。(在yield表达式中)
close方法:
调用时不要参数,用于停止生成器。
模拟生成器
当旧版本不能使用时生成器时,需要普通函数模拟生成器。
方式:1. result=[]防御函数体开始处。
2. yield some_expression 用result.append(some_expression)代替。
3.函数末尾添加return result
注:前面的递归生成器flatten就可以用普通函数重写模拟生成器。
案例总结