Scope of python variable in for loop

Solution 1:

The for loop iterates over all the numbers in range(10), that is, [0,1,2,3,4,5,6,7,8,9].
That you change the current value of i has no effect on the next value in the range.

You can get the desired behavior with a while loop.

i = 0
while i < 10:
    # do stuff and manipulate `i` as much as you like       
    if i==5:
        i+=3

    print i

    # don't forget to increment `i` manually
    i += 1

Solution 2:

Analogy with C code

You are imagining that your for-loop in python is like this C code:

for (int i = 0; i < 10; i++)
    if (i == 5)
        i += 3;

It's more like this C code:

int r[] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
for (int j = 0; j < sizeof(r)/sizeof(r[0]); j++) {
    int i = r[j];
    if (i == 5)
        i += 3;
}

So modifying i in the loop does not have the effect you expect.

Disassembly example

You can look at the disassembly of the python code to see this:

>>> from dis import dis
>>> def foo():
...     for i in range (0,10):
...         if i==5:
...             i+=3
...         print i
... 
>>> dis(foo)
  2           0 SETUP_LOOP              53 (to 56)
              3 LOAD_GLOBAL              0 (range)
              6 LOAD_CONST               1 (0)
              9 LOAD_CONST               2 (10)
             12 CALL_FUNCTION            2
             15 GET_ITER            
        >>   16 FOR_ITER                36 (to 55)
             19 STORE_FAST               0 (i)

  3          22 LOAD_FAST                0 (i)
             25 LOAD_CONST               3 (5)
             28 COMPARE_OP               2 (==)
             31 POP_JUMP_IF_FALSE       47

  4          34 LOAD_FAST                0 (i)
             37 LOAD_CONST               4 (3)
             40 INPLACE_ADD         
             41 STORE_FAST               0 (i)
             44 JUMP_FORWARD             0 (to 47)

  5     >>   47 LOAD_FAST                0 (i)
             50 PRINT_ITEM          
             51 PRINT_NEWLINE       
             52 JUMP_ABSOLUTE           16
        >>   55 POP_BLOCK           
        >>   56 LOAD_CONST               0 (None)
             59 RETURN_VALUE        
>>> 

This part creates a range between 0 and 10 and realizes it:

          3 LOAD_GLOBAL              0 (range)
          6 LOAD_CONST               1 (0)
          9 LOAD_CONST               2 (10)
         12 CALL_FUNCTION            2

At this point, the top of the stack contains the range.

This gets an iterator over the object on the top of the stack, i.e. the range:

         15 GET_ITER  

At this point, the top of the stack contains an iterator over the realized range.

FOR_ITER begins iterating over the loop using the iterator at the top of th estack:

    >>   16 FOR_ITER                36 (to 55)

At this point, the top of the stack contains the next value of the iterator.

And here you can see that the top of the stack is popped and assigned to i:

         19 STORE_FAST               0 (i)

So i will be overwritten regardless of what you do in the loop.

Here is an overview of stack machines if you haven't seen this before.