10

Why is the following simple loop not saving the value of i at the end of the loop?

for i in range( 1, 10 ):
    print i
    i = i + 3

The above prints:

1
2
3
4
5
6
7
8
9

But it should print:

1
4
7
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Nishant Singh
  • 3,055
  • 11
  • 36
  • 74
  • Possibly [related explanation](http://stackoverflow.com/questions/35618307/how-to-transform-string-into-dict/35618686#35618686). – Ian Mar 03 '16 at 09:57
  • 8
    Why would that even work that way? This is completely counter intuitive. – Andrey Mar 03 '16 at 09:58
  • 2
    your variable is being set in the "for", printed and then you do the addition. If you want to that output you should "print i+3" – miguels Mar 03 '16 at 09:59
  • Related: [Readable, controllable iterators?](http://stackoverflow.com/a/34734307/4532996) – cat Mar 03 '16 at 15:15
  • 4
    Two close votes for *primarily opinion based*? Seriously? I don't see *anything* opinion based here, except that the OP has the wrong opinion about how `for` works, but the question itself has a definite answer. If you think this is a poor/useless question downvote. – Bakuriu Mar 03 '16 at 16:25
  • 1
    @Andrey Think in terms of a C `for` loop, where changing the iteration variable within the body also changes the iterations – Izkata Mar 03 '16 at 17:17
  • @Izkata but in C it is more explicit, if you have x += 5 it is explicitly increasing. – Andrey Mar 03 '16 at 21:20

1 Answers1

41

for sets i each iteration, to the next value from the object being iterated over. Whatever you set i to in the loop is ignored at that point.

From the for statement documentation:

The suite is then executed once for each item provided by the iterator, in the order of ascending indices. Each item in turn is assigned to the target list using the standard rules for assignments, and then the suite is executed.

i is the target list here, so it is assigned each value from the range(1, 10) object. Setting i to something else later on doesn't change what the range(1, 10) expression produced.

If you want to produce a loop where you alter i, use a while loop instead; it re-tests the condition each time through:

i = 1
while i < 10:
    print i
    i += 3

but it'll be easier to just use a range() with a step, producing the values up front:

for i in range(1, 10, 3):
    print i
Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
  • and how do i make this not happen ? – Nishant Singh Mar 03 '16 at 09:57
  • 15
    @NishantSingh you can control the step in your `range(1,10,3)` – Ian Mar 03 '16 at 09:57
  • Good answer ! Key point here is that there is no testing going on. For loop in python is an actual loop, an iteration, rather than `do-test-repeat` for loop of other languages. In java, I think, there is `for each` loop, which is more similar to the python loop; perhaps such naming makes it a little more clear how that loop behaves, right ? – Sergiy Kolodyazhnyy Mar 03 '16 at 16:28
  • 2
    I think `for x in iterable:` and `foreach (x in iterable) {` is almost identical, from a comprehension standpoint. The only issue here is that `i in range(1,10)` is actually a boolean expression when not used within the context of a for loop. Therefore someone might get confused with a while loop. For loops in many languages are a bit of a misnoma IMO. They're really while loops but with some syntactic sugar on. – Will S Mar 03 '16 at 16:57
  • 1
    @WillS: Indeed, there's probably something to be said about the difference between `for i in range(1,10)` and `while i in range(1,10)` here; they do two very different things, even though, to a beginning programmer, the difference may seem subtle and arbitrary. – Ilmari Karonen Mar 03 '16 at 17:29