Reputation: 964
I'm having some confusion with regards to a generator that I am using to create a sum of squares in python. Essentially I am iterating over vectors stored in a dictionary and finding the SS with another target vector.
I'm trying to code more pythonically by using list comprehension and generators but am struggling to understand how this is meant to work. The function that 'generates' just returns a string
<generator object distance.<locals>.operation at 0x00000181748E2048>
Which is obviously wrong. Any advice would be appreciated. Ideally want to output the result of the SS operation but also interested in how I am misunderstanding this.
import math
v = [2,-2,1,3]
dv = {'a1':[0,1,3,5], 'a2':[2,5,6,7], 'a3':[1,-2,-3,2], 'a4':[2,2,1,1],
'a5':[3,2,1,-1]}
def distance(v, dv):
def operation(orig, nbr):
yield [sum(math.sqrt(orig - nbr) for orig, nbr in zip(orig, nbr))]
for k in sorted(dv):
l = dv[k]
list = operation(v,l)
print(list)
distance(v, dv)
Upvotes: 2
Views: 813
Reputation: 109526
You don't need yield
as you are returning a list. The below sum
function in operation
is actually a generator expression than accomplishes the same thing.
Thus, sum([x ** 0.5 for x in some_list])
becomes sum(x for x in some_list)
using a generator expression which uses less memory.
def distance(v, dv):
def operation(orig, nbr):
return sum(abs(orig - nbr) ** 0.5 for orig, nbr in zip(orig, nbr))
return [operation(v, dv[l]) for l in sorted(dv)]
>>> distance(v, dv)
[5.974691494688162, 6.8818192885643805, 4.0, 3.414213562373095, 5.0]
Upvotes: 2
Reputation: 213223
You're using generators wrong way. That yield
will anyways only be executed once (provided you convert the return value to a list). And it's result in not even used in a generator expression.
You can change that code to something like this:
def operation(orig, nbr):
for orig, nbr in zip(orig, nbr):
yield math.sqrt(abs(orig - nbr))
for k in sorted(dv):
l = dv[k]
value = sum(operation(v,l))
print(value)
Now, this is using the generator function properly. Everytime the sum()
function needs the next value, the for
loop inside operation()
function will be executed 1 step
, and it will yield the next sqrt
value, until it is exhausted.
Upvotes: 3
Reputation: 5825
You want to use list(operation(v, l))
. Generators are yielded as a generator object and so you have to explicitly convert them to a list using list()
.
Explained with examples here.
Upvotes: 3