Reputation: 7048
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
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
Reputation: 22561
answer
is generator object, you can make (generate) list from it:
result = list(answer)
Upvotes: 2
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