Step 6 - The Intermediate Function Issue

Our current concept uses generator functions to call generator functions. But what about normal functions calling generators in between?

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 intermediate_function():
    print(intermediate_function.__name__, 1)
    generator_two()
    print(intermediate_function.__name__, 2)


def chaining_generator():
    print(chaining_generator.__name__, 1)
    yield from generator_one()
    print(chaining_generator.__name__, 2)
    intermediate_function()
    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
intermediate_function 1
intermediate_function 2
chaining_generator 3
main_generator 2
Loop finished

As we can see the intermediate_function has run but generator_two is never executed. The intermediate_function is blocking our generator based code from being executed as expected. The only way to fix this is to run another loop in the intermediate_function or to use the yield from statement again. But using yield from would also convert the normal function into a generator function.

Summary

  • Calling coroutines from normal functions breaks the concept.

  • Therefore normal functions must not call coroutines.

  • Coroutines are allowed to call normal functions.