Home > Back-end >  Python coroutine can one `send` without first doing `next`?
Python coroutine can one `send` without first doing `next`?

Time:04-20

When sending a value to a generator/coroutine, is there a way to avoid that initial next(g)?

def gen(n):
    m = (yield) or "did not send m to gen"
    print(n, m)

g = gen(10)
next(g)
g.send("sent m to g") # prints "10 sent m to g"

Without next(g), we get

TypeError: can't send non-None value to a just-started generator

CodePudding user response:

The error stems from this bit of code in CPython's gen_send_ex2, i.e. it occurs if gi_frame_state is FRAME_CREATED.

The only place that matters for this discussion that sets gi_frame_state is here in gen_send_ex2, after a (possibly None) value has been sent and a frame is about to be evaluated.

Based on that, I'd say no, there's no way to send a non-None value to a just-started generator.

CodePudding user response:

Not sure if this is helpful in your specific case, but you could use a decorator to initialize coroutines.

def initialized(coro_func):
    def coro_init(*args, **kwargs):
        g = coro_func(*args, **kwargs)
        next(g)
        return g
    return coro_init


@initialized
def gen(n):
    m = (yield) or "did not send m to gen"
    print(n, m)


g = gen(10)
g.send("sent m to g") # prints "10 sent m to g"
  • Related