st4rgut - 1 year ago 66
Python Question

# NameError when reordering for statements in a list comprehension

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.

An array

`a`
equals
`[[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]]`

List Comprehension 1 Works:

``````[(i,j) for j in range(len(a[i])) for i in range(len(a))]
``````

Returns:

``````[(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)]
``````

As expected.

But flipping the variables...

``````[(j,i) for i in range(len(a[j])) for j in range(len(a))]
``````

Results in a NameError:name 'j' is not defined

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

It's not the order of the variables that matters here. In fact, running List Comprehension 1 does not work either, for the same reason as List Comprehension 2. I'm guessing you had defined `i` earlier in the program, which is why List Comprehension 1 worked for you. The problem is the order of the `for` loops.

I'll try to explain by example. If you were to write it like this, it would run fine:

``````[ [(i,j) for j in range(len(a[i]))] for i in range(len(a))]
``````

Note the square brackets I added. In this case, the `for` loop with `i` happens first, and only then the `for` loop with `j`. (It should be noted, however, that this will return a list of lists of tuples.) Alternately, this would also run fine:

``````[(i,j) for i in range(len(a)) for j in range(len(a[i]))]
``````

When both `for` loops are written together that way (no extra brackets this time), they're read left-to-right.

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download