Getting a Generator Object returned when I want the data
<p>I am very very new to Python 3, so please be nice.</p>

<p>I have looked at all the documentation I could find regarding this - there does seem to be a lot, it's just I still cannot figure out what to do.</p>

<p>This is my code:</p>

<pre><code>poly = [[36606.0,53223.0],[37332.0,52224.0],[39043.0,53223.0],
[41603.0,53223.0],[42657.0,53278.0],[43123.0,52060.0],
[44054.0,51156.0],[45806.0,51498.0],[46751.0,53237.0],
[46983.0,54606.0],[45861.0,57057.0],[44971.0,58836.0],
[44054.0,60616.0],[43451.0,58138.0],[41850.0,59179.0],
[40850.0,60370.0],[39906.0,59233.0],[38674.0,59179.0],
[35566.0,56249.0],[37592.0,57536.0]]

def perimeter():
     return (sum((abs((x1 - x0)**2)+abs((y1 - y0)**2))**.5)
                        for ((x0, y0), (x1, y1)) in parts1(poly))

def parts1(poly):
    return poly[0:] + [poly[0]]

print(perimeter())
</code></pre>

<p>It is running <em>without</em> any errors but I am getting a return of:</p>

<p><code>generator object perimeter.locals.genexpr at 0x7f47d8671c50</code></p>

<p>How do I make it so that it gives me the value/answer?
I am really not sure what is going on.</p>

<p>The first problem is that you have your parentheses in the wrong places. You want to call <code>sum()</code> on a generator expression, but instead you have written a generator expression using <code>sum()</code>. So you might try this:</p>

<pre><code>def perimeter():
    return sum(((x1 - x0) ** 2) + ((y1 - y0) ** 2) ** .5
                 for (x0, y0), (x1, y1) in parts1(poly))
</code></pre>

<p>(I have also taken out your <code>abs()</code> calls, since squaring a number will make it positive, making <code>abs()</code> irrelevant, and deleted some unnecessary parentheses.)</p>

<p>But this still doesn't work: now you get <code>'float' object is not iterable</code>.</p>

<p>This is because you are trying to unpack four values from each element of the list, but each element contains only two. Python unpacks each element to two floats, then tries to unpack each float to two variables. This is where the error message rears its ugly head.</p>

<p>So you need to change <code>parts1()</code> to return a list of a list of lists of lists. That is, each item in the list is a list, which contains two lists, each containing the coordinates of a point (a given point and its successor). One way to do this is to use the built-in <code>zip()</code> function with an offset or rotated copy of the list.</p>

<pre><code>def parts1(poly):
    return zip(poly, poly[1:] + poly[:1])
</code></pre>

<p>Finally, you don't really need the separate function <code>parts1()</code>âit can go right in the <code>perimeter()</code> function. And you should pass <code>poly</code> into <code>perimeter()</code>.</p>

<pre><code>def perimeter(poly):
    return sum(((x1 - x0) ** 2) + ((y1 - y0) ** 2) ** .5
                 for (x0, y0), (x1, y1) in zip(poly, poly[1:] + poly[:1]))
</code></pre>

<p>You could do this without the extra copy of the list by iterating over the coordinates in <code>poly</code> and keeping track of the last items you saw. But you couldn't write it as a generator expression. Instead you'd use a regular <code>for</code> loop.</p>

<pre><code>def perimeter(poly):
    x0, y0 = poly[-1][0], poly[-1][1]
    per = 0.0
    for x1, y1 in poly:
        per += ((x1 - x0) ** 2) + ((y1 - y0) ** 2) ** .5
        x0, y0 = x1, y1
    return per 
</code></pre>

<p>Not quite as succinct, and not as fast either, but doesn't use as much memory.</p>

python python-3.x generator