1.何为生成器
生成器就是一种迭代器。生成器拥有next方法并且行为与迭代器完全相同,这意味着生成器也可以用于Python的for循环中。生成器是一种普通的函数语法定义的迭代器。任何包含yield语句的函数称为生成器。即我们定义一个生成器就是定义一个普通的函数,但是在函数里面使用yield关键字,调用生成器函数时将返回一个生成器。
def generator_func():
yield 1
yield 2
generator = generator_func() #生成器函数返回一个生成器
print (generator)
>>>
<generator object generator_func at 0x021D2D28>
2.生成器的特性
(1)第一次调用next()时,生成器才开始执行生成器函数,直到遇到yield时暂停执行(挂起),并且yield的参数作为此次执行的返回值;之后每次执行生成器的next方法都是从暂停的位置恢复执行,直到再次遇到yield又停止,并且yield的参数又作为next方法的返回值;如果调用next方法时,生成器函数结束(遇到空的return语句或者到函数末尾),则该次next方法会抛出StopIteration异常(即for循环的终止条件)。
【注】调用生产器函数只是返回了一个生成器。
print (next(generator))
print (next(generator))
print (next(generator)) #生产器已经结束,抛出StopIteration
>>>
1
2
Traceback (most recent call last):
File "C:\Users\Administrator\Desktop\test_python.py", line 9, in <module>
print (next(generator))
StopIteration
(2)生成器在每次暂停执行时,生成器类的所有变量都被封存在生成器中。并在恢复执行时复原。同一个生成器函数返回的不同生成器之间相互独立。
def fab_generator_func():
yield 1
yield 1
f1 = 1
f2 = 1
while True: #这里一定是死循环
f1,f2 = f2,f1+f2
yield f2
for g1 in fab_generator_func(): #自动调用迭代器next方法
if(g1 > 10):break
print (g1,)
for g2 in fab_generator_func(): #自动调用迭代器next方法
if(g2 > 10):break
print (g2,)
>>>
1 1 2 3 5 8
1 1 2 3 5 8
3.生成器方法
send方法:外部作用域访问生成器的send方法,就像访问next方法一样,只不过前者使用一个参数(要发送的消息)。
def generator_func(value):
while True:
new = (yield value)
if new is not None:value = new
g = generator_func(42)
print (next(g))
g.send('Hello,Lsj')
print (next(g))
>>>
42
Hello,Lsj
【注】也就是说,send()和next()方法能访问到迭代器
close方法:用于停止生成器。对关闭的生成器后再次调用next或send将抛出StopIteration异常。
throw方法(使用异常类型调用,还有可选的值以及回溯对象):用于在生成器内部引发一个异常。
4.生成器需要注意的问题
生成器函数时可以带参数的,但是它不可以return一个值,因为生成器函数已经有一个默认的返回值--生成器,所以不能有其他的返回值,即使是return None也不行。但是可以以空的return语句结束。同时可以在try/finally中的finally使用yield语句。
def generator_func():
yield 1
yield 2
return
g = generator_func()
print (next(g))
print (next(g))
print (next(g))
>>>
1
2
Traceback (most recent call last):
File "C:\Users\Administrator\Desktop\test_python.py", line 8, in <module>
print (next(g))
StopIteration