[Python-ideas] iterating over a generator while sending values
Clay Gerrard
clay.gerrard at gmail.com
Thu Mar 27 21:16:50 CET 2014
Hi,
I often use generators when I want to bake some smarts into my producers in
a typical producer and consumer pattern. Twice in the past year or so on
different projects after a few iterations on my producer/consumer
code ("iterations", ha!) I would eventually find I wanted my consumer to
send some simple feedback to the producer - when using generators send
works great for this!
I normally start here:
q = producer()
def consume(q):
for item in q:
success = handle(item)
But then ended up here:
def consume(q):
success = None
while True:
try:
item = q.send(success)
except StopIteration:
break
success = handle(item)
But this always feels clunky; almost "out of order" - I've normally got
some logging and other bits in there. I'm just trying to iterate over the
queue, the StopIteration just feels like noise.
It seems I always started out with a simple iteration and then end up
refactoring in the send function once I realize I need to add something
extra into my producer:
I want to just say:
def consume(q):
for item in q:
success = handle(item)
q.send(success) # oh how I wish I could just add this here!
But I can just "tack on" the send because it consumes too, so I have to
rephrase the "simple" iteration into a "while True try except StopIteration
break" - yuk.
I normally just end up adding a little helper function, which I've named
"sending" and use it like this:
def consume(q):
for item in sending(q, lambda: success):
success = handle(item)
^ much closer to the original iterative code!
Here's the implementation if you didn't already guess:
# this function is missing from stdlib for some reason...
def sending(g, sender):
"""
Iterate over g with send
:params g: the iterable
:params sender: the callable returning the value to send
"""
yield g.next()
while True:
yield g.send(sender())
This will raise StopIteration as soon as g is exhausted, but since the
caller is already consuming "sending" with a for loop it all works ok in
the end.
Does anyone else have a different way of iterating over a generator while
sending values? Does everyone just already have a similar function stuck
in their bag? Does this happen to other folks frequently enough that a
generalizable solution could be added to stdlib? Maybe it's too simple to
be worth anyone's time or i'm missing something that already works better...
Thanks!
-clayg
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/python-ideas/attachments/20140327/6748d86d/attachment.html>
More information about the Python-ideas
mailing list