Python nested for loop behaviour

for-loop, nested-loops, python

Solution

The `for` loop assigns a new value to `i` every loop iteration, namely the next value taken from the loop iterable (in this case `range(16)`.

You can modify `i` in the loop itself, but that doesn't alter the iterable `for` is working with.

If you wanted to change the loop iterable, then you'd have to do so directly on the iterable:

loop_iterable = iter(range(16))
for i in loop_iterable:
    if i == 0:
        for j in range(8):
            print 'i is (if) ' + str(i)
            i = next(loop_iterable)
    else:
        print 'i is (else)' + str(i)

Here, we create a iterator object from the `range(10)` sequence by using the `iter()` function; the `for` statement does the exact same thing under the hood, but now we can address the iterator directly. The `next()` function advances the iterator to the next value, just like the `for` loop would do.

However, it may be easier to just use a `while` loop instead:

i = 0
while i < 16:
    if i == 0:
        for j in range(8):
            print 'i is (if) ' + str(i)
            i = next(loop_iterable)
    else:
        print 'i is (else)' + str(i)
    i += 1

The thing to remember is that the Python `for` loop statement is nothing like a C or Java or JavaScript `for` loop. It is a Foreach loop instead. `range()` simply generates a sequence of numbers to loop over, as opposed to a C-style `for` loop, which combines the initial assignment (`i = 0`), test (`i < 16)`) and loop incrementer (`i += 1`) into one statement.

Problem

I came across this weird behaviour with nested for loops and I can't for the light of me explain this. Is this a python-specific thing or am I just overseeing something? This is the code I'm running: ``` for i in range(16): if i == 0: for j in range(8): print 'i is (if) ' + str(i) i = i + 1 else: print 'i is (else)' + str(i) ``` This is the output I'm getting: ``` i is (if) 0 i is (if) 1 i is (if) 2 i is (if) 3 i is (if) 4 i is (if) 5 i is (if) 6 i is (if) 7 i is (else)1 i is (else)2 i is (else)3 i is (else)4 i is (else)5 i is (else)6 i is (else)7 i is (else)8 i is (else)9 i is (else)10 i is (else)11 i is (else)12 i is (else)13 i is (else)14 i is (else)15 ``` This is the output I'm expecting: ``` i is (if) 0 i is (if) 1 i is (if) 2 i is (if) 3 i is (if) 4 i is (if) 5 i is (if) 6 i is (if) 7 i is (else)8 i is (else)9 i is (else)10 i is (else)11 i is (else)12 i is (else)13 i is (else)14 i is (else)15 ``` It seems like the i in the outer for loop and the i in the inner for loop are different variables, although that seems completely counterintuitive to me. Any input (I'm fairly new to python but couldn't find documentation on this)

Original source