rtindru rtindru - 17 days ago 6
Python Question

Python Block Scopes - Someone explain this

I ran this block of code and the output was surprising. I know that I am reusing i, my question is why doesn't the loop exit after the first iteration since i is reassigned!

Code:

for i in range(3):
print '====='
print 'Outer I: ', i
print '====='
for j in range(2):
print 'J', j
for i in range(5):
print 'Inner I', i
print '====='
print 'Outer I Again: ', i
print '====='


Output:

=====
Outer I: 0
=====
J 0
Inner I 0
Inner I 1
Inner I 2
Inner I 3
Inner I 4
J 1
Inner I 0
Inner I 1
Inner I 2
Inner I 3
Inner I 4
=====
Outer I Again: 4
=====
=====
Outer I: 1
=====
J 0
Inner I 0
Inner I 1
Inner I 2
Inner I 3
Inner I 4
J 1
Inner I 0
Inner I 1
Inner I 2
Inner I 3
Inner I 4
=====
Outer I Again: 4
=====
=====
Outer I: 2
=====
J 0
Inner I 0
Inner I 1
Inner I 2
Inner I 3
Inner I 4
J 1
Inner I 0
Inner I 1
Inner I 2
Inner I 3
Inner I 4
=====
Outer I Again: 4


Here are things that are confusing:


  • I would expect the loop to break after the first iteration, but it
    does not.

  • For the same reason, the first print statement "Outer I"
    prints the correct value of i.

  • The second outer print statement
    "Outer I Again" prints the wrong value.



I'm running this on Python 2.7 with CPython.

Answer

There is no inner i or outer i in this code, there is a single i variable which is assigned in two different loops. Why should the loop break after the first iteration? Python's for is basically a for each loop in other languages, it iterates on the members of the iterator or generator given. the range function returns the list of elements [0,1,2,3,4], and each iteration i is given the next value from the list, the current value of i doesn't matter to the outer loop.

This is why the first Outer I prints the i value you expect but the second one (after the inner loop) does not.