[Python-ideas] yield * (Re: Missing operator.call)

Greg Ewing greg.ewing at canterbury.ac.nz
Sun Feb 8 23:46:54 CET 2009

Nick Coghlan wrote:

> One important question to ask yourself is whether the semantics you want
> may make more sense as a new generator method (as happened with the
> addition of send() and throw()) rather than as new syntax.
>   def f():
>     c = g()
>     yield *c
>     print c.result()

That turns one line into three and makes it impossible
to embed it in an expression. It's a very poor substitute
for what I have in mind.

> In particular, the return value of 'yield *' would likely still by
> needed for send() in the case where the subgenerator has already
> terminated, so the only sensible destination for the sent value is the
> generator that invoked 'yield *'

The effect I'm after is the same as what would happen if
the subgenerator were yielding directly to the caller of
the outer generator. Since, except for the first send(), it's
only possible to send() something to a generator when it's
suspended in a yield, anything sent to the outer generator
after the subgenerator terminates would have to appear as
the return value of some later (ordinary) yield in the
outer generator itself or another subgenerator.

The full expansion, taking sends into account, of

   result = yield *g()

would be something like

   _g = g()
     _v = yield _g.next()
     while 1:
       _v = yield _g.send(_v)
   except StopIteration, _e:
     result = _e.return_value

I think I've got that right. While it may look like the
last value assigned to _v gets lost, that's not actually
the case, because the last next() or send() call before
_g terminates never returns, raising StopIteration instead.

(Here I'm assuming the return value is passed back as an
argument to the StopIteration exception, something that I
think got proposed at one point but never adopted. The
return value could alternatively be attached to the
generator-iterator itself.)


More information about the Python-ideas mailing list