asyncio
works by using yield
, which is incredibly cool. yield
is similar to return
except it produces values you can loop over and it's lazily evaluated. def foo(): yield from [0, 1, 2] return 0 def bar(): print(yield from foo()) for x in bar(): print(x)
next
to only request one value. If it's at the end, it'll raise StopIteration(return_value)
. import random def gather(*tasks): # Store them in dicts by index to return the results in the right order. pending_tasks = dict(enumerate(tasks)) finished_tasks = dict() # Keep evaluating tasks until every task is finished. while len(pending_tasks) > 0: # Randomly select a pending task. index, task = random.choice(list(pending_tasks.items())) try: # Work on the pending task. yield next(task) except StopIteration as e: # If finished, save the result and remove it from the pending tasks.