Say I have an existing function that consumes an iterable, e.g.:
def printall(iterable):
for item in iterable:
print(item)
The point is, the function already exists and I don't want to have to clone or modify it.
But I'd like to feed it with some nontrivial processing. Pseudocode:
push_handle = XXXX()
printall(push_handle)
# printall() is now waiting on next(iter(iterable))
for item0 in some_source():
statement
statement
item1 = some_transformation(item0)
push_handle.send(item1)
# at this point printall() iterates once and resumes waiting
I'm aware that I could refactor the above loop to be a generator itself:
def processing(iterable):
for item0 in iterable:
statement
statement
item1 = some_transformation(item0)
yield item1
printall(processing(some_source()))
Even so, it feels to me as though an "adapter" of the form sketched above would be useful, eliminating the need to refactor.
I've worked with Python generators, but I keep getting stumped by the fact that in a generator function, yield implicitly yields to the original caller. I imagine a class containing two generator methods, one whose yield expression receives send() calls and the other of which yields to some other caller -- but transferring control from one to the other is the disconnect.
I could do this with threads and queues, but that feels too heavyweight for the purpose.
Similarly, I could use eventlet.queue.Queue(0), but the producer and consumer would have to be run on different eventlet greenthreads.
This feels as though it should be as straightforward as coding yield, but I'm stuck. Am I overlooking something?