defsimple_coro2(a): print("Started: a = " , a) b = yield a print("Received: b = " , b) c = yield a + b print("Received: c = " , c) """ >>> from test import simple_coro2 >>> my_coro2 = simple_coro2(14) >>> next(my_coro2) Started: a = 14 14 可以看到上面的一个next语句,将协程一直运行到第一个yield 产出值后的位置 >>> my_coro2.send(28) Received: b = 28 42 可以看到一个send语句完成了对b的赋值与下一个yield语句产出值两个功能。 >>> my_coro2.send(99) Received: c = 99 Traceback (most recent call last): File "<stdin>", line 1, in <module> StopIteration """
# BEGIN CORO_AVERAGER defaverager(): total = 0.0 count = 0 average = None whileTrue: # <1> # 下面的这一句话有两个含义:1.产出yield 2.接收一个值并赋给term term = yield average # <2> total += term count += 1 average = total/count # END CORO_AVERAGER
""" A coroutine to compute a running average # BEGIN CORO_AVERAGER_TEST >>> coro_avg = averager() # <1> >>> next(coro_avg) # <2> >>> coro_avg.send(10) # <3> 10.0 >>> coro_avg.send(30) 20.0 >>> coro_avg.send(5) 15.0 # END CORO_AVERAGER_TEST """
defcoroutine(func): """Decorator: primes `func` by advancing to first `yield`""" @wraps(func) defprimer(*args,**kwargs):# <1> gen = func(*args,**kwargs) # <2> next(gen) # <3> return gen # <4> return primer
协程定义:
1 2 3 4 5 6 7 8 9 10 11 12
from coroutil import coroutine # <4>
@coroutine # <5> defaverager():# <6> total = 0.0 count = 0 average = None whileTrue: term = yield average total += term count += 1 average = total/count
defsimple_coro2(a): print("Started: a = " , a) b = yield a print("Received: b = " , b) c = yield a + b print("Received: c = " , c) """ >>> from test import simple_coro2 >>> my_coro2 = simple_coro2(14) >>> next(my_coro2) Started: a = 14 14 >>> my_coro2.send(28) Received: b = 28 42 >>> my_coro2.send(99) Received: c = 99 Traceback (most recent call last): File "<stdin>", line 1, in <module> StopIteration """
defsimple_coro2(a): print("Started: a = " , a) b = yield a print("Received: b = " , b) c = yield a + b print("Received: c = " , c) """ >>> from test import simple_coro2 >>> coro = simple_coro2(14) >>> next(coro) Started: a = 14 14 >>> coro.send("abc") Received: b = abc Traceback (most recent call last): File "<stdin>", line 1, in <module> File "F:\git_localRepository\fluentPython\example-code\16-coroutine\test.py", line 5, in simple_coro2 c = yield a + b TypeError: unsupported operand type(s) for +: 'int' and 'str' >>> """
Result = namedtuple('Result', 'count average') defaverager(): total = 0.0 count = 0 average = None whileTrue: term = yield if term isNone: break# <1> total += term count += 1 average = total/count return Result(count, average) # <2>
# BEGIN YIELD_FROM_AVERAGER from collections import namedtuple
Result = namedtuple('Result', 'count average')
# the subgenerator defaverager():# <1> total = 0.0 count = 0 average = None whileTrue: term = yield# <2> if term isNone: # <3> break total += term count += 1 average = total/count return Result(count, average) # <4>
# the client code, a.k.a. the caller defmain(data):# <8> results = {} for key, values in data.items(): group = grouper(results, key) # <9> next(group) # <10> for value in values: group.send(value) # <11> group.send(None) # important! <12>
# print(results) # uncomment to debug report(results)
# output report defreport(results): for key, result insorted(results.items()): group, unit = key.split(';') print('{:2} {:5} averaging {:.2f}{}'.format( result.count, group, result.average, unit))