# -*- coding: utf-8 -*- """ Created on Sun Jan 6 14:17:00 2016 @author: kurner Demonstrates a driver-along-road pattern where the Driver(road) instance runs to completion when the target of 'yield from'. This is not about interweaving event processing asynchonously. It's about 'yield from' and how the iterator pattern lends itself to setting up coroutines, wherein a driver (future, task) experiences "maturation" (evolving state) based on traversing a road that keeps continuing where it left off. """ from random import choice from time import sleep import sys def road(co_id): """a bumpy road... keeps relinquishing control back to the driver """ drv = yield None drv.result = 1 drv.co_id = co_id drv = yield drv sleep(0.5) drv.result += 1 drv.name = choice(["Alvin", "Eric", "Gwen"]) drv = yield drv drv.result += 1 drv.color = choice(["Red", "Purple", "Orange"]) drv = yield drv drv.result += 1 drv.age = 100 sleep(0.5) return drv # the driver registers changes made along the way class Driver: """Iterator for driving along a road""" def __init__(self, r): self.g = r # on your mark... self.g.send(None) # get set... self.counter = 1 def __iter__(self): return self def __next__(self): while True: # go! ...drive to end of road try: self.counter *= 10 self = self.g.send(self) # expect delays except StopIteration as exc: return exc.value # returned by yield from tasks = [Driver(road(n)) for n in range(4)] # a Driver is instanced per road def delegator(task): return (yield from task) # delegating to a task (blocking once started) coroutines = (delegator(x) for x in tasks) # each based on yield from print("Non-blocking to here.") sys.stdout.flush() results = [ ] for co in coroutines: results.append(co.send(None)) # go! drives each task to completion for result in results: print("Result: {co_id}: {name} {color}".format(**result.__dict__))