NameError when reordering for statements in a list comprehension
<p>Hi please bear with me as I'm an amateur programmer. I'm learning list comprehensions and am getting 2 different results by switching variables though they look like they should work the same. </p>

<p>An array <code>a</code> equals <code>[[0, 0, 0, 0, 0], [1, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0]]</code></p>

<p>List Comprehension 1 Works: </p>

<pre><code>[(i,j) for j in range(len(a[i])) for i in range(len(a))] 
</code></pre>

<p>Returns: </p>

<pre><code>[(0, 0), (1, 0), (2, 0), (3, 0), (4, 0), (0, 1), (1, 1), (2, 1), (3, 1), (4, 1), (0, 2), (1, 2), (2, 2), (3, 2), (4, 2), (0, 3), (1, 3), (2, 3), (3, 3), (4, 3), (0, 4), (1, 4), (2, 4), (3, 4), (4, 4)]
</code></pre>

<p>As expected. </p>

<p>But flipping the variables...</p>

<pre><code>[(j,i) for i in range(len(a[j])) for j in range(len(a))]
</code></pre>

<p>Results in a NameError:name 'j' is not defined</p>

<p>Can someone please explain to me why it matters whether i or j comes first?</p>

<p>When you have a double <code>for</code> loop in a single list comprehension it's equivalent to doing those <code>for</code> loops in the same order using "traditional" <code>for</code> loops. So</p>

<pre><code>result = [(j,i) for i in range(len(a[j])) for j in range(len(a))]
</code></pre>

<p>is (almost exactly) equivalent to</p>

<pre><code>result = []
for i in range(len(a[j])):
    for j in range(len(a)):
        result.append((j, i))
</code></pre>

<p>As you can see, when you do <code>len(a[j])</code> the variable <code>j</code> doesn't exist, which is why you get that <code>NameError</code>.</p>

<p>BTW, your first list comp shouldn't work either. I suspect that you've defined <code>i</code> earlier in your code, which is why you don't get a <code>NameError</code>. Here's a slightly improved version of that list comp which assumes that <code>a</code> is a matrix, i.e., all of its sublists are the same length, and that it contains at least one sublist.</p>

<pre><code>[(i,j) for j in range(len(a[0])) for i in range(len(a))]
</code></pre>

<p>We could also do</p>

<pre><code>[(j, i) for i in range(len(a)) for j in range(len(a[0]))]
</code></pre>

<p>Both of those list comps create this list:</p>

<pre><code>[(0, 0), (1, 0), (2, 0), (3, 0), (4, 0), (0, 1), (1, 1), (2, 1), (3, 1), (4, 1), (0, 2), (1, 2), (2, 2), (3, 2), (4, 2), (0, 3), (1, 3), (2, 3), (3, 3), (4, 3), (0, 4), (1, 4), (2, 4), (3, 4), (4, 4)]
</code></pre>

python list