sayth
sayth

Reputation: 7048

Iteration on nested list and generators and yield

I was looking at creating a simple generator to sum the values of two list with nested values. Using from stack this answer https://stackoverflow.com/a/17014386/461887 and this answer What does the "yield" keyword do in Python?

So I created 2 lists

a = ([1, 2], [2, 3])

b = ([3, 4], [5, 6])

created a generator which errored.

In [10]: def sumNest(item1, item2):
    ...:     try:
    ...:         for i in iter(item1):
    ...:             for j in iter(item2):
    ...:                 yield i + j
    ...:     except TypeError:
    ...:         yield item
    ...:         

I can create it without error but it doesn't work(in the way I expect).

In [14]: def sumNest(item1, item2):
    ...:     try:
    ...:         for i in iter(item1):
    ...:             for j in iter(item2):
    ...:                 k = (i + j)
    ...:                 yield k
    ...:     except TypeError:
    ...:         yield item
    ...:         

Result of my use expecting the summed output.

In [17]: sumNest(a, b)
Out[17]: <generator object sumNest at 0x7f313e6e74b0>

In [18]: answer = sumNest(a, b)

In [19]: answer
Out[19]: <generator object sumNest at 0x7f313e6e7230>

In [20]: print answer
<generator object sumNest at 0x7f313e6e7230>

In [21]: answer(a, b)
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-21-badcb4bdaf5d> in <module>()
----> 1 answer(a, b)

TypeError: 'generator' object is not callable

Which led me to go back a bit and get this result where instead of addition of lists as expected I ended up with concatentation.

a = ([1, 2], [2, 3])

b = ([3, 4], [5, 6])

for i in a:
    ...:     for j in b:
    ...:         print(i + j)
    ...:         
[1, 2, 3, 4]
[1, 2, 5, 6]
[2, 3, 3, 4]
[2, 3, 5, 6]

Now thats a nice result, but not again expected(addition expected) so a result like:

([4, 6], [7, 9])

What is it that I am not getting about iteration, lists and yeild that I need to?

Upvotes: 2

Views: 2195

Answers (3)

Martijn Pieters
Martijn Pieters

Reputation: 1122392

A generator object needs to be looped over:

for summed in sumNest(a, b):
    print summed

Alternatively, you can use the next() function on a generator to get one value from it.

Your first example had a syntax error, because you misspelled yield. Your exception handler tries to yield item, but the function doesnt actually define that name.

Note that neither of your solutions flattens the lists, you are still 'summing' tuples.

Working example:

>>> a = ([1, 2], [2, 3])
>>> b = ([3, 4], [5, 6])
>>> def summedProduct(iter1, iter2):
...     for i in iter(iter1):
...         for j in iter(iter2):
...             yield i + j
... 
>>> for summed in summedProduct(a, b):
...     print summed
... 
[1, 2, 3, 4]
[1, 2, 5, 6]
[2, 3, 3, 4]
[2, 3, 5, 6]

If instead you wanted to flatten the lists, flatten them first, then zip() the flattened results together to sum:

def summedNested(nested1, nested2):
    flattened1 = (v for nested in nested1 for v in nested)
    flattened2 = (v for nested in nested2 for v in nested)
    for i, j in zip(flattened1, flattened2):
        yield i + j

Demo:

>>> def summedNested(nested1, nested2):
...     flattened1 = (v for nested in nested1 for v in nested)
...     flattened2 = (v for nested in nested2 for v in nested)
...     for i, j in zip(flattened1, flattened2):
...         yield i + j
... 
>>> for summed in summedNested(a, b):
...     print summed
... 
4
6
7
9

Upvotes: 2

ndpu
ndpu

Reputation: 22561

answer is generator object, you can make (generate) list from it:

result = list(answer)

Upvotes: 2

thefourtheye
thefourtheye

Reputation: 239513

Simply calling a generator will give you a generator object. You need to iterate it or use next function with it, to get the values. For example,

next(sumNest(a, b))

would have worked for you. Or iterating with a loop

for item in sumNext(a, b):
    print item

For example

def sumNest(item1, item2):
  try:
      for i in iter(item1):
          for j in iter(item2):
              k = (i + j)
              yield k
  except TypeError:
      yield item1

print next(sumNest([1, 2], [3, 4]))
print
for item in sumNest([1, 2], [3, 4]):
    print item,

Output

4

4 5 5 6

And when you say, I created 2 lists

a = ([1, 2], [2, 3])
b = ([3, 4], [5, 6])

you created tuples not lists.

Upvotes: 1

Related Questions