2

I ran this Python code.

for i in range(1,11):

    i=i*2

    print(i,end=" ")

It gave the following output: 2 4 6 8 10 12 14 16 18 20

How is the 'i' reaching 20 and yet staying inside the loop? Is there a new instance of 'i' being created somehow?

6
  • 1
    i is set anew from the next value in the range() sequence. You can't update it in the loop, because you are not altering the iterator. Commented Apr 26, 2017 at 9:03
  • the last time through the loop, i starts out as 10. you then multiply i by 2 before printing it, so you print 20 when you start the loop with i=10. Commented Apr 26, 2017 at 9:04
  • range(1,11) is something called a "generator" and it contains 10 specific values (1 through 10 inclusive), which it yields one at a time. Each time through the for statement, i is set to the next up of those values (1 through 10 inclusive). As Martijn said, nothing you do inside the loop affects which i is up next from your range statement the next time through your loop. Commented Apr 26, 2017 at 9:07
  • 2
    @MaxPower: range() is not a generator. It is a sequence, just like a list or a tuple or a string. Ranges have a length, you can index into them, you ran reverse ranges. Commented Apr 26, 2017 at 9:15
  • thanks for the correction Martijn. Commented Apr 26, 2017 at 9:20

1 Answer 1

3

for sets the target variable each iteration. range() provides the values for this, nothing else. You can set i inside the loop body to anything you like, but that doesn't alter what the range() sequence will produce for the next iteration.

This is what happens:

  • An iterator is created for the range(1, 11) sequence. It consists of a reference to the range object and and index, starting at 0.
  • The next value is taken from the iterator, range(1, 11)[0], producing 1
    • i = 1 is executed, and the loop body is started
    • In the loop body, i = i * 2 is executed, setting i to 2
    • i is printed, the loop body ends
  • The iterator index is incremented to 1.
  • The next value is taken from the iterator, range(1, 11)[1], producing 2
    • i = 2 is executed, and the loop body is started
    • In the loop body, i = i * 2 is executed, setting i to 4
    • i is printed, the loop body ends
  • The iterator index is incremented to 2.
  • The next value is taken from the iterator, range(1, 11)[2], producing 3
    • i = 3 is executed, and the loop body is started
    • In the loop body, i = i * 2 is executed, setting i to 6
    • i is printed, the loop body ends

This continues on until the loop body for range(1, 11)[9] has been processed; there is no range(1, 11)[10] so the loop ends.

At no point does setting i to a different value in the loop alter how the loop runs. You'd have to alter the iterable, the object the for loop iterates over, to alter how the loop runs:

>>> list_of_numbers = [1, 2, 3, 4]
>>> for i in list_of_numbers:
...     discard = list_of_numbers.pop()  # making the list shorter!
...     print(i)
...
1
2

Now the loop ends early, because we removed elements from the iteratable, and the end is reached 'early'.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.