Recall from lesson 2-1 that indexing starts at 0, so for s = "loop" the value of s[0] is "l", the first character.
That numbering is about to matter again. Loops and indexes work together constantly, and the for loop in this lesson visits a string's characters in exactly the same order those index numbers describe, starting at the front and moving one position at a time.
for: do something for each item
Loops are the reason computers beat hand work. Check 10,000 rows, resize every photo in a folder, send a message to every subscriber: each is a few lines repeated automatically. From here on, nearly every useful program you write in this course, and on the job, has a loop in the middle.
A for loop runs its indented body once per item in a sequence. A string is a sequence, so this visits every character:
for ch in "abc": print(ch)
ch is the loop variable: Python assigns it the next character before each pass through the body.
range: a sequence of numbers on demand
When you want to repeat something N times or count, use range():
range(5)produces 0, 1, 2, 3, 4 (starts at 0, stops before 5)range(2, 6)produces 2, 3, 4, 5range(0, 10, 2)produces 0, 2, 4, 6, 8 (the third number is the step)
The stop value is excluded, exactly like string slices in lesson 2-1. range(5) has 5 items, which makes repeat 5 times read naturally.
Three loops, three sequences
Each loop below runs its body once per item. Counting the output lines against the range rules above is the quickest way to internalize them.
for ch in "abc": print(ch) for i in range(3): print("beep", i) for i in range(2, 6): print(i)
Output
a b c beep 0 beep 1 beep 2 2 3 4 5
The first loop treats the string as a sequence of characters and makes three passes. The second shows why range(5) means five repetitions: range(3) yields 0, 1, and 2, three values that stop before the number given. The third supplies both ends and produces 2 through 5, stopping before 6, so it makes four passes rather than the five a careless reading of 2, 6 might suggest.
A times table is the standard first use of a counting loop, with the loop variable appearing twice in each line of output.
for i in range(1, 6): print(f"5 x {i} = {5 * i}")
Output
5 x 1 = 5 5 x 2 = 10 5 x 3 = 15 5 x 4 = 20 5 x 5 = 25
The range starts at 1 because the table does, and it stops at 6 so that 5 is the last value included. Getting that upper bound right is the usual stumbling point, since range(1, 5) would quietly print only four rows. Inside the body, one set of braces shows i itself while the other computes 5 * i, so a single f-string produces the whole line.
Counting downward with a negative step
A negative third argument makes range count down instead of up. Here it starts at 10 and subtracts 2 each pass.
for i in range(10, 0, -2): print(i)
Output
10 8 6 4 2
The stop value is still excluded, which is why the sequence ends at 2 and never reaches 0. That is easy to get wrong when counting down, because a loop meant to include 0 would need range(10, -1, -2). The rule does not change with direction: the loop stops as soon as the next value would pass the boundary.