前提条件: 如果函数含有yield就是生成器,执行过程中遇到yield就跳出。
举例: def gen(): for i in range(10): x = yield i print(x) g=ge() print(g.send(None))) print(g.send(2))
先说表达式x = yield i 如果这个表达式只是x = i, 相信每个人都能理解。即把i的值赋值给了x,而现在等号右边是一个yield i,所以先要执行yield i,然后才是赋值。 因为生成器遇到yield就跳出,所以yield把i值返回到了调用者那里。 这个表达式的下一步操作:赋值。却因为等号右边的yield被暂停了,换句话说x = yield i才执行了一半,当调用者通过send(var)回到生成器函数时是回到之前那个赋值表达式被暂停的那里,所以接下来执行x = yield i的另一半,那就是这个赋值操作啦,这个值正是调用者通过send(var)发送进生成器的值。
再举例: def consumer(): r = '' while True: n = yield r if not n: return print('[CONSUMER] Consuming %s...' % n) r = '200 OK'
def produce(c): c.send(None) n = 0 while n < 5: n = n + 1 print('[PRODUCER] Producing %s...' % n) r = c.send(n) print('[PRODUCER] Consumer return: %s' % r) c.close()
c = consumer() produce(c) 执行结果: [PRODUCER] Producing 1... [CONSUMER] Consuming 1... [PRODUCER] Consumer return: 200 OK [PRODUCER] Producing 2... [CONSUMER] Consuming 2... [PRODUCER] Consumer return: 200 OK [PRODUCER] Producing 3... [CONSUMER] Consuming 3... [PRODUCER] Consumer return: 200 OK [PRODUCER] Producing 4... [CONSUMER] Consuming 4... [PRODUCER] Consumer return: 200 OK [PRODUCER] Producing 5... [CONSUMER] Consuming 5... [PRODUCER] Consumer return: 200 OK
官方说明: 注意到consumer函数是一个generator,把一个consumer传入produce后: 首先调用c.send(None)启动生成器;然后,一旦生产了东西,通过c.send(n)切换到consumer执行;consumer通过yield拿到消息,处理,又通过yield把结果传回;produce拿到consumer处理的结果,继续生产下一条消息;produce决定不生产了,通过c.close()关闭consumer,整个过程结束。
我的理解:
请注意produce()函数的最开始的地方是c.send(None),正如上面所说这个操作是初始化generator,并做第一个yield(遇到consumer函数就返回),它是有值的,他的值r为'',如果你执行命令行的话,你会发现结果先空了一行,就是他的功劳。 然后到n=0+1=1,此时执行c.send(1) ,它开始的位置是在给consumer函数中的n赋值,即[CONSUMER] Consuming 1 ,继续执行命令,此时r被赋值为‘200 ok’ ,因为while True 会一直循环,所以继续重来,但是生成器遇到yield 会自动跳出,此时跳出结果变成为r=‘200 ok’。
补充知识:
while True :
只有遇到continue 和break才能跳出循环。在生成器里面遇到yield也能。
if not x:相当于if x is not None和
if not x is None`
在python中 None, False, 空字符串"", 0, 空列表[], 空字典{}, 空元组()都相当于False