send() to a generator in a "for" loop with continue(val)??
Aaron Brady
castironpi at gmail.com
Fri Apr 17 22:07:23 EDT 2009
On Apr 17, 3:59 pm, Dale Roberts <goobe... at gmail.com> wrote:
> I've started using generators for some "real" work (love them!), and I
> need to use send() to send values back into the yield inside the
> generator. When I want to use the generator, though, I have to
> essentially duplicate the machinery of a "for" loop, because the "for"
> loop does not have a mechanism to send into the generator. Here is a
> toy example:
>
> def TestGen1():
> for i in xrange(3):
> sendval = yield i
> print " got %s in TestGen()" % sendval
>
> g = TestGen1()
> sendval = None
> try:
> while True:
> val = g.send(sendval)
> print 'val in "while" loop %d' % val
> sendval = val * 10
> except StopIteration: pass
>
> I have to explicitly create the generator with an assignment, send an
> initial None to the generator on the first go, then have to catch the
> StopIteration exception. In other words, replicate the "for"
> mechanism, but use send() instead of next().
>
> It would be nice if I could just do this instead:
>
> for val in TestGen1():
> print 'val in "for" loop %d' % val
> continue(val*10)
>
> ...or something similar. Is this an old idea? Has it been shot down in
> the past already? Or is it worth pursuing? I Googled around and saw
> one hit here:http://mail.python.org/pipermail/python-ideas/2009-February/003111.html,
> but not much follow-up.
>
> I wonder if people want to keep the idea of an "iterator" style
> generator (where send() is not used) separate from the idea of a "co-
> routine" style generator (where send() is used). Maybe combining the
> two idioms in this way would cause confusion?
>
> What do folks think?
>
> dale
You can do it with a wrapping generator. I'm not sure if it
interferes with your needs. It calls 'next' the first time, then just
calls 'send' on the parameter with the value you send it.
>>> def genf( ):
... x= True
... for _ in range( 10 ):
... i= yield( x )
... if i is None:
... i= not x
... x= i
...
>>> def for_send( gen ):
... x= next( gen )
... while 1:
... x= yield( x )
... x= gen.send( x )
...
>>> a= for_send( genf( ) )
>>> i= 0
>>> for x in a:
... print( i, x )
... i+= 1
... if not i% 3:
... _= a.send( False )
...
0 True
1 False
2 True
3 True
4 False
5 True
6 True
7 False
As you can see, it skips a beat every third iteration as directed.
More information about the Python-list
mailing list