1

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.

rtindru
  • 5,107
  • 9
  • 41
  • 59
  • Your code is wrong, you're reusing `i` variable in your inner loop: `for i in range(5):` – EdChum Nov 22 '16 at 10:45
  • do one thing and probably you will find what you want. replace **inner i** with another variable **k**. you will see it will work like magic!! ;) – Tanmaya Meher Nov 22 '16 at 10:50
  • 1
    There's no block scope in Python. See [Short Description of Scoping Rules](http://stackoverflow.com/questions/291978/short-description-of-scoping-rules) and [Block scope in Python](http://stackoverflow.com/questions/6167923/block-scope-in-python) – Zero Piraeus Nov 22 '16 at 10:50

3 Answers3

3

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.

Efi Weiss
  • 638
  • 6
  • 12
0

You're reusing the i variable in your inner loop:

for i in range(5)

so you see:

Outer I Again:  4

if you change it to a different variable name then it works as expected:

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

=====
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:  0
=====
=====
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:  1
=====
=====
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:  2
=====
EdChum
  • 376,765
  • 198
  • 813
  • 562
0

You are reusing the variables but the target variable remains same. In which case the scope of the variable does not change with the inside i. For working with immutable objects like strings or integers, you wouldn't face the issue. Use some other variable instead of the second i and you'll be good to go.

Ani
  • 710
  • 7
  • 19
  • Mutability has nothing to do with it – and the example *is* in fact working with integers, which you point out are immutable. – Zero Piraeus Nov 22 '16 at 10:58