Yield in a wrapper function

P

peterbe

This works exactly as you would expect::

from time import sleep
def foo(on='ABC'):
for e in list(on):
sleep(1)
yield e

When I run this on the command line It takes about 3 seconds to
complete and the first letter is shown after 1 second.
But, how do I wrap the function somewhere else::

from time import sleep
def foo(on):
for e in list(on):
sleep(1)
yield e

def wrapper(x):
if x < 0:
return foo('ABC')
else:
return foo('XYZ')

When I run this, variable three letters are shown and it takes 3
seconds for the whole thing to complete. The problem is that the whole
iteration is glogged up in the wrapper() function because the first
letter is shown after 3 seconds and then all letters are shown at the
same time.

How do I wrap functions that return iterators? ...if possible.
 
P

Peter Otten

from time import sleep
def foo(on):
for e in list(on):

Just

for e in on:
#...

is better. The list() constructor defeats much of the laziness you gain by
using a generator.
sleep(1)
yield e

def wrapper(x):
if x < 0:
return foo('ABC')
else:
return foo('XYZ')

When I run this, variable three letters are shown and it takes 3
seconds for the whole thing to complete. The problem is that the whole
iteration is glogged up in the wrapper() function because the first
letter is shown after 3 seconds and then all letters are shown at the
same time.

How do I wrap functions that return iterators? ...if possible.

The code you presented is OK. Your diagnosis is probably the result of a of
a misconstrued test case. Something like

for s in wrapper(1):
print s,

seems to work like you described because the text is buffered until the line
is complete. Try

for s in wrapper(1):
print s

or

import sys
for s in wrapper(1):
print s,
sys.stdout.flush() # explicitly flush the buffer

instead.

Peter
 
B

Bengt Richter

This works exactly as you would expect::

from time import sleep
def foo(on='ABC'):
for e in list(on):
sleep(1)
yield e

When I run this on the command line It takes about 3 seconds to
complete and the first letter is shown after 1 second.
But, how do I wrap the function somewhere else::

from time import sleep
def foo(on):
for e in list(on):
sleep(1)
yield e

def wrapper(x):
if x < 0:
return foo('ABC')
else:
return foo('XYZ')

When I run this, variable three letters are shown and it takes 3
seconds for the whole thing to complete. The problem is that the whole
iteration is glogged up in the wrapper() function because the first
letter is shown after 3 seconds and then all letters are shown at the
same time.

How do I wrap functions that return iterators? ...if possible.
Make the wrapper itself an iterable? E.g., is this the effect you wanted?
... for e in on:
... sleep(1)
... yield e
... ... if x < 0:
... for e in foo('ABC'): yield e
... else:
... for e in foo('XYZ'): yield e
... ...
ABC>>> ...
XYZ>>>

Regards,
Bengt Richter
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,770
Messages
2,569,584
Members
45,077
Latest member
SangMoor21

Latest Threads

Top