【流畅的python】16.1 - 生成器如何进化成协程

在生成器中加入yield关键字后,生成器调用方可以向生成器传入值,只需要使用.send(...)方法就可以传送数据。发送的数据会成为生成器函数中yield表达式的值。所以生成器可以作为协程使用。

协程是指一个过程,在这个过程中与调用方协作,产出由调用方提供的值。(协程并不等于生成器)

 

.send(...)方法是生成器API中增加的方法(在python2.5实现的),除了这个方法外,还添加了.throw(...)和.close(..)方法:

  1. throw()方法是让调用方抛出异常, 在生成器中处理
  2. close()方法则是终止生成器
 1 def gg():
 2     print('a')
 3     while True:
 4         b = yield
 5         print(b)
 6 n = gg()
 7 n.send(None) # 预激活协程,让函数gg运行到b = yield这一句
 8 print('-')
 9 n.send('b') # 给函数gg中的yield传值
10 n.throw(Exception,'value error') # 让调用方抛出异常,在生成器中处理
 1 # 输出为:
 2 
 3 a
 4 -
 5 b
 6 Traceback (most recent call last):
 7   File "c:/Users/heyufei/Desktop/test.py", line 20, in 
 8     n.throw(Exception,'value error') # 让调用方抛出异常,在生成器中处理
 9   File "c:/Users/heyufei/Desktop/test.py", line 14, in gg
10     b = yield
11 Exception: value error

 

.close(...)方法

 1 def gg():
 2     print('a')
 3     while True:
 4         b = yield
 5         print(b)
 6 n = gg()
 7 n.send(None) # 预激活协程,让函数gg运行到b = yield这一句
 8 print('-')
 9 n.send('b') # 给函数gg中的yield传值
10 n.close() # 终止生成器
11 n.send('bb') # 这句会报错

 

1 # 结果为:
2 a
3 -
4 b
5 Traceback (most recent call last):
6   File "c:/Users/heyufei/Desktop/test.py", line 22, in 
7     n.send('bb') # 给函数gg中的yield传值
8 StopIteration

在python3.3后,对生成器函数句法做了两处改动,以更好地作为协程使用:

生成器可以返回一个值,在这之前,如果在生成器中给return 语句提供值,会抛出SyntaxError错误

新引入了yield from句法,使用它可以把复杂的生成器重构成小型的嵌套生成器,省去了之前把生成器的工作委托给子生成器所需的大量样板代码

 

你可能感兴趣的