st4rgut - 9 months ago 45

Python Question

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`

`[[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?

Answer

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.

Source (Stackoverflow)