In [16]:
def simple_coroutine():
print('-> coroutine started')
x = yield
print('-> coroutine received:', x)
In [17]:
my_coro = simple_coroutine()
my_coro
Out[17]:
In [18]:
next(my_coro)
In [19]:
my_coro.send(42)
In [20]:
my_coro = simple_coroutine()
my_coro.send(1729)
In [21]:
def simple_coro2(a):
print('-> Started: a =', a)
b = yield a
print('-> Received: b =', b)
c = yield a + b
print('-> Received: c =', c)
In [22]:
my_coro2 = simple_coro2(14)
In [23]:
from inspect import getgeneratorstate
In [24]:
getgeneratorstate(my_coro2)
Out[24]:
In [25]:
next(my_coro2)
Out[25]:
In [26]:
getgeneratorstate(my_coro2)
Out[26]:
In [27]:
my_coro2.send(28)
Out[27]:
In [28]:
my_coro2.send(99)
In [29]:
getgeneratorstate(my_coro2)
Out[29]:
In [30]:
def averager():
total = 0.0
count = 0
average = None
while True:
term = yield average
total += term
count += 1
average = total / count
In [31]:
coro_avg = averager()
next(coro_avg)
coro_avg.send(10)
Out[31]:
In [32]:
coro_avg.send(30)
Out[32]:
In [33]:
coro_avg.send(5)
Out[33]:
In [34]:
from functools import wraps
In [35]:
def coroutine(func):
"""Decorator: primes 'func' by advancing to first 'yield'"""
@wraps(func)
def primer(*args, **kwargs):
gen = func(*args, **kwargs)
next(gen)
return gen
return primer
In [36]:
@coroutine
def averager():
total = 0.0
count = 0
average = None
while True:
term = yield average
total += term
count += 1
average = total / count
In [37]:
coro_avg = averager()
getgeneratorstate(coro_avg)
Out[37]:
In [38]:
coro_avg.send(10)
Out[38]:
In [39]:
coro_avg.send(30)
Out[39]:
In [40]:
coro_avg.send(5)
Out[40]:
In [41]:
coro_avg = averager()
coro_avg.send(40)
Out[41]:
In [42]:
coro_avg.send(50)
Out[42]:
In [43]:
coro_avg.send('spam')
In [44]:
coro_avg.send(60)
In [45]:
class DemoException(Exception):
"""An exception type for the demonstration"""
def demo_exc_handling():
print('-> coroutine started')
while True:
try:
x = yield
except DemoException:
print('*** DemoException handled. Continuing...')
else:
print('-> coroutine received: {!r}'.format(x))
raise RuntimeError('This line should never run.')
In [46]:
exc_coro = demo_exc_handling()
next(exc_coro)
In [47]:
exc_coro.send(11)
In [48]:
exc_coro.send(22)
In [50]:
exc_coro.close()
getgeneratorstate(exc_coro)
Out[50]:
In [51]:
exc_coro = demo_exc_handling()
next(exc_coro)
In [52]:
exc_coro.send(11)
In [53]:
exc_coro.throw(DemoException)
In [54]:
getgeneratorstate(exc_coro)
Out[54]:
In [55]:
exc_coro = demo_exc_handling()
next(exc_coro)
In [56]:
exc_coro.send(11)
In [57]:
exc_coro.throw(ZeroDivisionError)
In [58]:
getgeneratorstate(exc_coro)
Out[58]:
In [59]:
class DemoException(Exception):
"""An exception type for the demonstration"""
def demo_finally():
print('-> coroutine started')
try:
while True:
try:
x = yield
except DemoException:
print('*** DemoException handled. Continuing...')
else:
print('-> coroutine received: {!r}'.format(x))
finally:
print('-> coroutine ending')
In [66]:
from collections import namedtuple
Result_Averager = namedtuple('Result', 'count average')
def averager():
total = 0.0
count = 0
average = None
while True:
term = yield
if term is None:
break
total += term
count += 1
average = total / count
return Result_Averager(count, average)
In [67]:
coro_avg = averager()
next(coro_avg)
coro_avg.send(10)
coro_avg.send(30)
coro_avg.send(6.5)
coro_avg.send(None)
In [68]:
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
In [69]:
result
Out[69]:
In [70]:
def gen():
for c in 'AB':
yield c
for i in range(1, 3):
yield i
In [71]:
list(gen())
Out[71]:
In [73]:
def gen():
yield from 'AB'
yield from range(1, 3)
In [74]:
list(gen())
Out[74]:
In [75]:
def chain(*iterables):
for it in iterables:
yield from it
In [76]:
s = 'ABC'
t = tuple(range(3))
list(chain(s, t))
Out[76]:
In [1]:
from collections import namedtuple
Result = namedtuple('Result', 'count average')
# the subgenerator
def averager():
total = 0.0
count = 0
average = None
while True:
term = yield
if term is None:
break
total += term
count += 1
average = total / count
return Result(count, average)
# the delegating generator
def grouper(results, key):
while True:
results[key] = yield from averager()
# the client code, a.k.a. the caller
def main(data):
results = {}
for key, values in data.items():
group = grouper(results, key)
next(group)
for value in values:
group.send(value)
group.send(None) # important!
# print(results) #uncomment to debug
report(results)
def report(results):
for key, result in sorted(results.items()):
group, unit = key.split(';')
print('{:2} {:5} averaging {:2f}{}'.format(
result.count, group, result.average, unit))
data = {
'girls; kg': [40.9, 38.5, 44.3, 42.2, 45.2, 41.7, 44.5, 38.0, 40.6, 44.5],
'girls; m': [1.6, 1.51, 1.4, 1.3, 1.41, 1.39, 1.33, 1.46, 1.45, 1.43],
'boys; kg': [39.0, 40.8, 43.2, 40.8, 43.1, 38.6, 41.4, 40.6, 36.3],
'boys; m': [1.38, 1.5, 1.32, 1.25, 1.37, 1.48, 1.25, 1.49, 1.46],
}
In [8]:
from taxi_sim import taxi_process
In [9]:
taxi = taxi_process(ident=13, trips=2, start_time=0)
In [10]:
next(taxi)
Out[10]:
In [11]:
taxi.send(_.time + 7)
Out[11]:
In [12]:
taxi.send(_.time + 23)
Out[12]:
In [13]:
taxi.send(_.time + 5)
Out[13]:
In [14]:
taxi.send(_.time + 48)
Out[14]:
In [15]:
taxi.send(_.time + 1)
Out[15]:
In [16]:
taxi.send(_.time + 10)
In [ ]: