Step 5 - A runnable Example¶
Lets take a look at our current concept by using a runnable example.
Loop v1¶
def loop(coroutine):
"""Loop v1"""
step = 1
while True:
print("Loop step", step)
try:
next(coroutine)
step += 1
except StopIteration as e:
return e.value
from loop import loop
def generator_one():
print(generator_one.__name__, 1)
yield
print(generator_one.__name__, 2)
def generator_two():
print(generator_two.__name__, 1)
yield
print(generator_two.__name__, 2)
yield
print(generator_two.__name__, 3)
def chaining_generator():
print(chaining_generator.__name__, 1)
yield from generator_one()
print(chaining_generator.__name__, 2)
yield from generator_two()
print(chaining_generator.__name__, 3)
def main_generator():
print(main_generator.__name__, 1)
yield from chaining_generator()
print(main_generator.__name__, 2)
result = loop(main_generator())
print("Loop finished with result", result)
Output:
Loop step 1
main_generator 1
chaining_generator 1
generator_one 1
Loop step 2
generator_one 2
chaining_generator 2
generator_two 1
Loop step 3
generator_two 2
Loop step 4
generator_two 3
chaining_generator 3
main_generator 2
Loop finished with result None
As a sequence diagram:
sequenceDiagram
participant l as loop
participant mg as Main Generator
participant cg as Chaining Generator
participant g1 as Generator One
participant g2 as Generator Two
activate l
activate l
l->>mg: next
deactivate l
activate mg
activate mg
mg->>cg: yield from
deactivate mg
activate cg
activate cg
cg->>g1: yield from
deactivate cg
activate g1
activate g1
g1-->>l: yield
deactivate g1
activate l
l->>g1: next
deactivate l
activate g1
g1->>cg: return
deactivate g1
deactivate g1
activate cg
cg->>g2: yield from
deactivate cg
activate g2
activate g2
g2-->>l: yield
deactivate g2
activate l
l->>g2: next
deactivate l
activate g2
g2-->>l: yield
deactivate g2
activate l
l->>g2: next
deactivate l
activate g2
g2->>cg: return
deactivate g2
deactivate g2
activate cg
cg->>mg: return
deactivate cg
deactivate cg
activate mg
mg->>l: return
deactivate mg
deactivate mg
deactivate l
Summary
We have learned so far:
yield
suspends execution of a coroutine.Using
yield from
suspends the execution back to the initial caller at the root - the loop.The loop resumes the execution where the last
yield
was executed.A loop is easiest to be implemented as a function that gets a single coroutine passed as argument. This coroutine may call other coroutines.