I don't understand generator.send()

Chris Angelico rosuav at gmail.com
Sat May 14 20:47:09 EDT 2011


On Sun, May 15, 2011 at 10:08 AM, Victor Eijkhout <see at sig.for.address> wrote:
>        yield i

>        r = gen.send(2)

When you send() something to a generator, it becomes the return value
of the yield expression. See the example here:
http://docs.python.org/whatsnew/2.5.html#pep-342-new-generator-features

For what you're doing, there's a little complexity. If I understand,
you want send() to be like an ungetc call... you could do that like
this:


def ints():
   i=0
   while True:
       sent=(yield i)
       if sent is not None:
          yield None  # This becomes the return value from gen.send()
          yield sent  # This is the next value yielded
       i += 1

This lets you insert at most one value per iteration. Supporting more
than one insertion is more complicated, but changing the loop
structure entirely may help:

def ints():
    i=0
    queue=[]
    while True:
        if queue:  # see other thread, this IS legal and pythonic and
quite sensible
            sent=(yield queue.pop(0))
        else:
            sent=(yield i)
            i+=1
        if sent is not None:
            yield None  # This is the return value from gen.send()
            queue.append(sent)

With this generator, you maintain a queue of sent values (if you want
it to be a LIFO stack rather than a FIFO queue, just change the pop(0)
to just pop()), and if the queue's empty, it produces sequential
integers. (Incidentally, the sent values don't have to be integers. I
leave it to you to decide whether that's any use or not.)

Hope that helps!

Chris Angelico



More information about the Python-list mailing list