生成器
【生成器】
生成器是用来创建python序列的一个对象,使用它可以迭代庞大的序。通常,生成器是为迭代器产生数据的。
生成器概念:
生成器不会把结果保存到一个系列中,而是保存生成器的状态,在每次进行迭代的时计算并返回一个值,值遇到StopIteration异常就结束
生成器表达器表达式:
与列表解析语法相似,只不过把列表解析的[换乘()
生成器所能作的事,列表解析都能做,只是数据较大的时候,列表解析比较费内存
简单的生成器表达式示例
>>> gen=(x**2 for x in range(5))
>>> gen.next()
0
>>> gen.next()
1
>>> gen.next()
4
>>> gen.next()
9
>>> gen.next()
16
>>> gen.next()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
StopIteration
【生成器函数】
Yield函数的重要作用在于可以保存函数的状态;
在函数中如果出现了关键字yield,那么该函数就不在是普通的函数,而是生成器函数,生成器函数可以产生一个无限的序列,列表解析是无法这么做的;
下面看一下示例:
[root@wish1 413]# cat y1.py
#!/usr/bin/env python
def counNum():
for i in range(4):
return i
print "hello"
a=counNum()
print a
运行结果:
root@wish1 413]# python y1.py
0
return只返回了for循环的第一次,函数走到return就不在执行 了,所以hello并没有打印出来。
把return换成yield来看一下结果
[root@wish1 413]# cat y2.py
#!/usr/bin/python
def countNum():
for i in range(4):
yield i
a=countNum()
print a.next()
print a.next()
print a.next()
运行结果:
[root@wish1 413]# python y2.py
0
1
下面再通过几个例子来看一下生成器的强大
#!/usr/bin/env python
def odd():
n=1
while True:
yield n
n+=2
od=odd()
count=1
for i in od:
if count>=5:
break
print i
count+=1
生成器最大的特点就是可以接收外部传入的一个变量并根据变量内容计算结果后返回
#!/usr/bin/python
def gen():
value=0
while True:
receive=yield value
if receive=='e':
break
value='got:%s' %receive
g=gen()
print(g.send(None))
print(g.send(None))
print(g.send('aaa'))
print(g.send(3))
print(g.send('e'))
执行结果:
[root@wish1 408]# python 3.py
0
got:None
got:aaa
got:3
Traceback (most recent call last):
File "3.py", line 14, in <module>
print(g.send('e'))
StopIteration
执行流程:
. 通过g.send(None)或者next(g)可以启动生成器函数,并执行到第一个yield语句结束的位置。此时,执行完了yield语句,但是没有给receive赋值。yield
value会输出初始值0注意:在启动生成器函数时只能send(None),如果试图输入其它的值都会得到错误提示信息。
- 通过g.send(‘aaa’),会传入aaa,并赋值给receive,然后计算出value的值,并回到while头部,执行yield value语句有停止。此时yield value会输出”got:
aaa”,然后挂起。 - 通过g.send(3),会重复第2步,最后输出结果为”got: 3′′
当我们g.send(‘e’)时,程序会执行break然后推出循环,最后整个函数执行完毕,所以会得到StopIteration异常。
总结:- 按照鸭子模型理论,生成器就是一种迭代器,可以使用for进行迭代。
- 第一次执行next(generator)时,会执行完yield语句后程序进行挂起,所有的参数和状态会进行保存。再一次执行next(generator)时,会从挂起的状态开
始往后执行。在遇到程序的结尾或者遇到StopIteration时,循环结束。 - 可以通过generator.send(arg)来传入参数,这是协程模型。
next()等价于send(None)