-5

I don't understand how python deals with variables with same names in a program, especially in for loops.

The following is a python program

for i in range(10):
    if i%2!=0:
        print i
        continue
    i += 2
    print i

The outcome is as follows

2
1
4
3
6
5
8
7
10
9

I don't understand why I get the above-mentioned outcome. In my opinion, when i is 0, the program will execute i+=2, so i becomes 2, and is printed out. Then the for finishes one loop so that i is increased by 1. So after the first loop, i should become 3. I test my opinion using the following C++ program, the result is exactly what I expect.

#include <iostream>
using namespace std;

int main(int argc, char const *argv[])
{
    int i;
    for (i = 0; i < 10; ++i)
    {
        if(i%2!=0){
            cout << i << endl;
            continue;
        }
        i += 2;
        cout << i << endl;
    }
    return 0;
}

The outcome is as follows:

2
3
6
7
10

Why is the result of python program looks like that?

To further exploit the reasons, I add more print sentences to the python program as follows:

for i in range(10):
    print 'round ', i
    if i%2!=0:
        print 'in if, i = ',i
        continue
    print 'before i+=2, i is ',i
    i += 2
    print 'after i+=2, i is ',i

Then the outcome becomes:

round  0
before i+=2, i is  0
after i+=2, i is  2
round  1
in if, i =  1
round  2
before i+=2, i is  2
after i+=2, i is  4
round  3
in if, i =  3
round  4
before i+=2, i is  4
after i+=2, i is  6
round  5
in if, i =  5
round  6
before i+=2, i is  6
after i+=2, i is  8
round  7
in if, i =  7
round  8
before i+=2, i is  8
after i+=2, i is  10
round  9
in if, i =  9

It seems python treat i's differently in different parts of the program. It implicitly declares another variable named i. But why? And what is the rule of python to decide whether to declare a new variable implicitly?

klutt
  • 30,332
  • 17
  • 55
  • 95
pfc
  • 1,831
  • 4
  • 27
  • 50
  • 1
    if I recall correctly, in python you can't alter the forloop variable so if you are manipulating it it gets reset on the next iteration as to what it should be based on the loop iteration. Hope this helps – N. Ivanov Jan 16 '18 at 14:53
  • 2
    Apparently `for i in range(10):` in python isn't the same as `for (i = 0; i < 10; ++i)` in C – Support Ukraine Jan 16 '18 at 14:54
  • I suggest removing the C and C++ tags since this is a Python question. – Thomas Matthews Jan 16 '18 at 14:56
  • By the way, your question title is a little misleading since your question is not about different variables with the same name, but involves operations on a single variable. – Some programmer dude Jan 16 '18 at 15:18

3 Answers3

3

It doesn't matter how you modify i inside the loop, the next iteration a new value will be fetched from the range object and the value of i will be overwritten.

So the Python loop

for i in range(10): ...

is not equivalent to the C loop

for (i = 0; i < 10; i = i + 1) { ... }

which uses the current value of i to calculate the new value. Instead it's more equivalent to

for (i = 0; i < 10; i = get_next_value()) { ... }

where get_next_value() doesn't consider the current value of i at all.

Some programmer dude
  • 400,186
  • 35
  • 402
  • 621
1

Python simply draws elements from the iterable produced by range(10) and binds i to each of these elements, that's it. So, what Python is doing is:

iterable = range(10)

try:
    while True:
        i = next(iterable) # this is important!

        # this is your code
except StopIteration:
    pass

As you can see, you can modify i the way you want, but it will be set equal to next(iterable) right on the next iteration.

ForceBru
  • 43,482
  • 10
  • 63
  • 98
0

This is what you get when you run range(10) in a python (2.7) shell:

>>> range(10)
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

So what your code is doing is the same as

for i in [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]:
    #the rest of the code...

Which means i is set to the next value in the array at each iteration, regardless of what you did with i in the previous iteration

Obs:

As was pointed out, in python 3 range(10) actually creates a range object range(0,10), which will function like the list above in your example but isn't exactly the same thing. It's an object that stores only the start, stop and step values so as not to store the whole list, and calculates items as needed.

For the purpose of understanding what's going on in your question they're gonna be pretty much the same

Fabio
  • 3,015
  • 2
  • 29
  • 49