Question

I have a function that yields 2 parts of a list:

>>> x = [1,2,3,4,5,6]
>>> def fold(ls):
...     for i in range(0,2):
...             yield x[:i]
...             yield x[i:]
...

I understand that it still returns as 1 generator although there're more than 1 yield in the function:

>>> fold(x)
<generator object fold at 0x13f9320>
>>> t1, t2 = fold(x)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: too many values to unpack

To access them, I have could:

>>> for i in fold(x):
...     print i
... 
[]
[1, 2, 3, 4, 5, 6]
[1]
[2, 3, 4, 5, 6]

I want to perform different operation on these two, so i would need some sort of access like this:

>>> for i in fold(x):
...     t1, t2 = i
...     print t1, t2 # because 
... 
Traceback (most recent call last):
  File "<stdin>", line 2, in <module>
ValueError: need more than 0 values to unpack

I could use some tricks on the odd/even-ness of the yields and do the following but is there any other way?

>>> for i,j in enumerate(fold(x)):
...     if i & 0x1:
...             print 't1', j
...     else:
...             print 't2', j
... 
t2 []
t1 [1, 2, 3, 4, 5, 6]
t2 [1]
t1 [2, 3, 4, 5, 6]
Was it helpful?

Solution

Just yield a tuple:

yield x[:i], x[i:]

Then you can do:

for i in fold(x):
    t1, t2 = i

or even better

for t1, t2 in fold(x):
    ...

Side note: the first ValueError comes from the fact that you are trying to unpack a generator. No matter what the generator is you will always get this exception if number of variables on the left side is different then the number of items the generator will yield. This is a coincidence, but what you were looking for is probably something like this:

t1, t2 = list(fold(x))[0]

OTHER TIPS

If you can't change the original generator as in freakish' answer, there is an easy way to make a generator that yields items from any iterable in pairs.

def pairwise(iterable):
    """Yield items from iterable two at a time. If the number of items in iterable is
    odd, the last one is never yielded."""
    iterator = iter(iterable)
    while True:
        # Use the fact that .next() raises StopIteration when done, as we
        # need to raise that too
        yield iterator.next(), iterator.next()

Now you can do

for t1, t2 in pairwise(fold(x)):
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top