Generator expression evaluation with several ... for ... in ... parts
<p><strong>Question</strong>: What does Python do under the hood when it sees this kind of expression?  </p>

<pre><code>sum(sum(i) for j in arr for i in j)
</code></pre>

<hr>

<p><strong>My thoughts</strong>: <em>The above expression works.</em> But as it is written in <a href="https://docs.python.org/3.5/reference/executionmodel.html#resolution-of-names" rel="nofollow">Python's docs</a>:</p>

<blockquote>
  <p>generator expressions are implemented using a function scope</p>
</blockquote>

<p>Not to be verbose :) I have an array with the following layout (<em>as an example</em>):  </p>

<pre><code>&gt;&gt;&gt; arr = [
           [[1,2,3], [4,5,6]],
           [[7,8,9],[10,11,12]]
          ]
</code></pre>

<p>At first, I try to sum all elements of <code>arr</code> with the following expression:</p>

<pre><code>&gt;&gt;&gt; sum(sum(i) for i in j for j in arr)
NameError: name 'j' is not defined
</code></pre>

<p>It raises <code>NameError</code>, but why not <code>UnboundLocalError: local variable 'j' referenced before assignment</code> if it is implemented using a function scope, what is evaluation rules for <code>for ... in ...</code> from left-to-right or from right-to-left? And what is an equivalent generator function for this generator expression?</p>

<hr>

<p><strong>EDIT</strong>:</p>

<p>I catch the idea. Thanks @vaultah for some insight. In this case <code>j</code> is the argument that is send to generator expression:</p>

<pre><code>&gt;&gt;&gt; sum(sum(i) for i in j for j in arr)  # NameError
</code></pre>

<p>that's why I get this weird <code>NameError</code>.  </p>

<hr>

<p><a href="http://stackoverflow.com/a/39552690/6793085">@Eric answer</a> shows that generator expression:</p>

<pre><code>&gt;&gt;&gt; sum(sum(i) for j in arr for i in j)
</code></pre>

<p>is equivalent to: </p>

<pre><code>&gt;&gt;&gt; def __gen(arr):
        for j in arr:
            for i in j:
                yield sum(i)

&gt;&gt;&gt; sum(__gen(arr))
</code></pre>

<hr>

<blockquote>
  <p>What does Python do under the hood when it sees this kind of expression?</p>

<pre><code> sum(sum(i) for j in array for i in j)
</code></pre>
</blockquote>

<p>It becomes something equivalent to:</p>

<pre><code>def __gen(it):
    # "it" is actually in locals() as ".0"
    for j in it:
        for i in j:
            yield sum(i)
sum(__gen(iter(arr)))
</code></pre>

<p>Note that both <code>__iter__</code> and the name resolution happen outside the function scope. This only applies to the first <code>for</code> loop</p>

<p><a href="https://www.python.org/dev/peps/pep-0289/#the-details" rel="nofollow">PEP 0289</a> explains this in more detail</p>

python python-3.x scope nested generator