example-code-2e/19-coroutine/coroaverager2.py
2021-02-14 20:58:46 -03:00

62 lines
1.3 KiB
Python

"""
A coroutine to compute a running average.
Testing ``averager`` by itself::
# tag::RETURNING_AVERAGER_DEMO1[]
>>> coro_avg = averager()
>>> next(coro_avg)
>>> coro_avg.send(10) # <1>
>>> coro_avg.send(30)
>>> coro_avg.send(6.5)
>>> coro_avg.send(None) # <2>
Traceback (most recent call last):
...
StopIteration: Result(count=3, average=15.5)
# end::RETURNING_AVERAGER_DEMO1[]
Catching `StopIteration` to extract the value returned by
the coroutine::
# tag::RETURNING_AVERAGER_DEMO2[]
>>> coro_avg = averager()
>>> next(coro_avg)
>>> coro_avg.send(10)
>>> coro_avg.send(30)
>>> coro_avg.send(6.5)
>>> try:
... coro_avg.send(None)
... except StopIteration as exc:
... result = exc.value
...
>>> result
Result(count=3, average=15.5)
# end::RETURNING_AVERAGER_DEMO2[]
"""
# tag::RETURNING_AVERAGER[]
from collections import namedtuple
Result = namedtuple('Result', 'count average')
def averager():
total = 0.0
count = 0
average = None
while True:
term = yield
if term is None:
break # <1>
total += term
count += 1
average = total/count
return Result(count, average) # <2>
# end::RETURNING_AVERAGER[]