South Plantation High School · Procedural Programming with Python
for Loops, range() & the in Operator
range() · Iterating strings and lists · The in operator · Lesson review
!
Review the lesson slides, then complete the assignment at the bottom of this page. Your assignment work is saved in this browser on this computer. When you check a task, your name, period, and which tasks are complete are shared with your teacher (your code is not). When you finish, print it or save it as a PDF to turn in.
1 / 16→ next · ← back · n notes · s script · f full
Lesson Review
for Loops & range()
forrange()in"Python"["a", "b"]
Repeating once for every item in a sequence.
By the end of this lesson you will be able to:
Write a for loop and explain what the loop variable holds each time.
Use range() with one, two, or three numbers, including counting down.
Loop through every character in a string and every item in a list.
Use the in operator to test if something is inside a sequence.
Choose between a for loop and a while loop.
How to use this page: Use Next and Back (or the arrow keys). In a TRY IT editor, click ▶ Run to watch the whole loop, or Step to go one line at a time. The badge on the for line shows which item the loop is on.
Words you will hear today
Word
What it means
Example
loop
Code that repeats
for, while
iteration
One trip through the loop body
range(5) means 5 iterations
sequence
An ordered group of items
range(5), "cat", [1, 2]
loop variable
The name that holds the current item
letter in for letter in word:
iterate
To go through items one at a time
"iterate over a list"
accumulator
A variable that builds up a result as the loop runs
total += n
A for loop repeats once for each item in a sequence.
A sequence is an ordered group of items: a range of numbers, a string, or a list.
Iteration = one trip through the body.
Last time we used while loops, which repeat as long as a condition is True. Today we learn the for loop, which repeats once for every item in a group. It is the loop you will use most in Python, because Python does the counting for you.
You must remember all three parts. Forget the update and the loop never ends.
for loop: Python manages it
for count in range(1, 6):
print(count)
1
2
3
4
5
The start, stop, and update all live inside range(1, 6). There is no update line to forget, so a for loop over a range always ends.
Where did the three parts go?
Part
In the while loop
In the for loop
Start
count = 1
the 1 in range(1, 6)
Keep going while...
count <= 5
the 6 (stop before 6)
Update
count += 1
automatic: the step is 1 by default
Both loops print the same thing. The for version is shorter, and it is impossible to forget the update, which is the most common cause of an infinite loop (a loop that never stops).
A for loop handles the start, stop, and update for you.
A for loop over a range or a string always ends.
range packs the start, stop, and update into one place.
Both programs print 1 to 5. The while version needs three separate pieces. The for version packs all of them into range. Fewer pieces means fewer places for bugs. And notice there is no update line, so it is very hard to write an infinite for loop.
for Loops
Anatomy of a for loop
forkeyword
letterloop variable
inkeyword
"Hi"sequence
:colon
····4 spaces
print(letter)indented body
The sequence is the group of items to go through: a range(), a string, or a list.
The loop variable is a name you choose. Each time through the loop, Python puts the next item into it.
When there are no items left, the loop ends and Python moves on to the line after the loop.
Pick a good name:for letter in word:, for fruit in fruits:, and for i in range(5): all read clearly. Short names like i are common for numbers.
What Python does, step by step, for for letter in "Hi":
Python takes the first item, "H", and stores it in letter. It runs the body: prints H.
Back to the top. The next item, "i", goes into letter. It runs the body again: prints i.
Back to the top. No items are left, so the loop ends and Python continues after the body.
You never write letter = ... yourself. The for line does the assigning for you, once per item.
Just repeating, not using the number? Some programmers name the variable _ (an underscore) to say "I don't need this value": for _ in range(3):.
for, loop variable, in, sequence, colon, indented body.
The loop variable holds a different item each iteration.
The for line assigns the loop variable for you, one item at a time.
Read a for loop out loud like a sentence: for each letter in "Hi", print the letter. Python takes the first item, puts it in the loop variable, runs the body, then grabs the next item. When it runs out of items, the loop is over.
range()
range(stop): count from 0
range(5) makes the numbers 0, 1, 2, 3, 4.
It starts at 0, not 1.
It stops before the number you give it. 5 is not included.
It still makes exactly 5 numbers, so range(5) is a quick way to repeat something 5 times.
for i in range(3):
print("Hip hip hooray!")
Hip hip hooray!
Hip hip hooray!
Hip hip hooray!
Memory trick: "range of 5 gives me 5 numbers, and the first one is 0."
rannever ran
Why start at 0?
Python counts positions starting at 0. The first letter of a string is at position 0, and the first item of a list is at position 0. Because range(5) gives 0 to 4, it lines up perfectly with the 5 positions of a 5-item list. You will see why that is handy when you study lists.
Seeing what a range holds
Printing range(5) shows just range(0, 5), because a range makes its numbers one at a time as the loop asks for them. To see them all at once, wrap it in list(): list(range(5)) shows [0, 1, 2, 3, 4].
range(n) gives 0 up to n - 1.
It always makes exactly n numbers.
list(range(5)) shows all the numbers at once.
This is the part that surprises everyone: range of 5 starts at 0 and stops at 4. Step through the editor and watch the badge on line 1 show i equals 0, then 1, and so on. On the last check there are no items left, and the loop ends.
range()
range(start, stop, step)
Code
Numbers
Meaning
range(5)
0, 1, 2, 3, 4
stop
range(1, 6)
1, 2, 3, 4, 5
start, stop
range(2, 11, 2)
2, 4, 6, 8, 10
start, stop, step
range(10, 0, -3)
10, 7, 4, 1
counting down
start is included. If you leave it out, it is 0.
stop is never included.
step is how much to add each time. If you leave it out, it is 1.
To include the last number, add 1 to stop. For 1 to 10, write range(1, 11).
range() explorer
Change the numbers and see exactly what the range makes.
How many numbers will I get?
With a step of 1, the count is simply stop − start. range(1, 6) gives 6 − 1 = 5 numbers. range(3, 10) gives 7 numbers.
Reading a range out loud
Say range(2, 11, 2) as "start at 2, go up by 2, and stop before reaching 11." Then list the numbers: 2, 4, 6, 8, 10. The next one, 12, would pass the stop, so the range ends.
The stop does not have to be hit exactly.range(0, 10, 3) gives 0, 3, 6, 9. The next value, 12, is past 10, so it stops. It does not matter that 10 itself was never reached.
start is included, stop is not.
Default start is 0, default step is 1.
range(1, n + 1) gives 1 through n.
With step 1, count = stop - start.
range can take one, two, or three numbers. The rule that never changes: start is in, stop is out. Use the explorer to try range of 1 comma 10, then 1 comma 11. Which one gives you the number 10?
range()
Try it: range in a loop
Change start, stop, and step, then run the loop. Try 1, 11, 1 (1 to 10), 0, 21, 5 (count by fives), and 10, 0, -1 (count down).
Try a step of 0. Python refuses with ValueError: range() arg 3 must not be zero, because the loop could never move forward.
Predict before you run
start, stop, step
Numbers
Why
1, 11, 1
1 to 10
11 is the stop, so it is left out
0, 21, 5
0, 5, 10, 15, 20
21 is just past 20, so 20 is included
10, 0, -1
10 down to 1
0 is the stop, so it is left out
5, 1, 1
(nothing)
counting up from 5 can never get to 1, so the loop runs 0 times
A range that makes no numbers is not an error. The loop body just never runs, and Python goes straight to the line after it. That makes this bug easy to miss.
A negative step counts down. The stop must then be smaller than the start.
A step of 0 is an error.
A range with no numbers runs the loop 0 times, with no error.
Now we can see range inside a real loop. Try counting down with 10, 0, negative 1. Notice it stops at 1, not 0, because stop is never included. What would you change to include 0? Right: make the stop negative 1.
range()
Counting down and adding up
Countdown
A negative step counts down. The stop must be smaller than the start.
Running total
The accumulator pattern works great with for. With limit 4: 1 + 2 + 3 + 4 = 10.
Why limit + 1? Because the stop is not included. range(1, limit + 1) goes from 1 all the way to limit.
Tracing the running total (limit = 4)
n
total before
total += n
total after
1
0
0 + 1
1
2
1
1 + 2
3
3
3
3 + 3
6
4
6
6 + 4
10
Two placement rules for an accumulator:total = 0 goes before the loop (or it would reset every time), and print goes after the loop (or it would print every partial total).
Countdown: range(start, 0, -1) ends at 1.
Accumulator: total = 0 before the loop, total += n inside.
total = 0 before the loop; print after the loop.
Two classic loops side by side. The countdown uses a negative step. The running total uses the same accumulator pattern as with while loops, but now range handles the counting. Compare this with the while version from last time: no update line needed.
Iterating Sequences
Looping through a string
A string is a sequence of characters. A for loop visits each character in order, from left to right.
for letter in "cat":
print(letter)
c
a
t
Spaces and punctuation are characters too, so they get a turn.
The loop runs once for each character. "cat" has 3, so it runs 3 times.
len("cat") tells you how many characters a string has.
Type any word or short sentence and run it.
Doing something with each character
The loop variable is a one-character string, so you can use it in any expression:
for letter in "hey":
print(letter.upper() * 2)
HH
EE
YY
The original string is not changed. The loop only reads each character. letter.upper() makes a new uppercase copy each time.
Each character, including spaces, is one item.
The loop runs len(text) times.
The loop reads characters; it does not change the string.
Strings are sequences, so a for loop can walk through them one character at a time. Try typing your name. Then try a phrase with a space in it and watch the loop variable become a space for one iteration.
Iterating Sequences
Looping through a list
A list holds several values in one variable. Write it with square brackets and commas between the items:
A for loop visits each item in the list, in order:
for fruit in fruits:
print("I like", fruit)
I like apple
I like mango
I like kiwi
Naming tip: name the list with a plural (fruits) and the loop variable with the singular (fruit). Then the loop reads like English.
Type your own list of items, separated by commas.
Lists can hold numbers too
scores = [88, 92, 75]
for score in scores:
print(score + 5) # a 5-point curve
93
97
80
The loop variable takes the type of each item. Here each score is an int, so math works. If the list held strings, each item would be a string.
Compare with a string:for x in "apple": gives 5 letters. for x in ["apple"]: gives 1 whole word, because the list has only one item.
Lists use square brackets and commas.
The loop variable holds one whole item each time, not one letter.
A list gives whole items; a string gives single characters.
Lists are how Python keeps a group of things together: a playlist, a class roster, a set of scores. A for loop goes through the items one at a time. Notice the difference from strings: here the loop variable holds a whole word each time, not a single letter.
The in Operator
The in operator: is it inside?
in checks whether a value is inside a sequence. The answer is True or False. not in gives the opposite answer.
Expression
Result
Why
"a" in "cat"
True
"a" is a letter in "cat"
"cat" in "concatenate"
True
a string can find a chunk of letters
"A" in "cat"
False
case sensitive
"kiwi" in ["apple", "kiwi"]
True
"kiwi" is an item in the list
"ki" in ["apple", "kiwi"]
False
a list needs a whole item to match
7 not in [1, 2, 3]
True
7 is not an item
in operator tester
Pick a value, a sequence type, and a sequence. Python checks it.
Using in to replace a long or
# long way
if day == "Sat" or day == "Sun":
print("Weekend!")
# with in
if day in ["Sat", "Sun"]:
print("Weekend!")
Both work the same, but the in version is shorter and easier to extend: just add more items to the list.
Ignoring capital letters:"A".lower() in "cat" is True, because .lower() turns "A" into "a" first.
in answers True or False.
In a string, it finds letters or chunks. In a list, it needs a whole item.
It is case sensitive.
x in [a, b, c] replaces x == a or x == b or x == c.
The in operator asks one question: is this inside that? For strings, it can find a single letter or a whole chunk of letters. For lists, it only matches complete items. Try searching a list for part of a word and see what happens.
The in Operator
Using in inside a loop
A loop and an if ... in test work great together. This program counts the vowels in a word:
The for loop visits each character.
if ch in "aeiouAEIOU": checks whether that character is a vowel.
vowels += 1 counts it.
Two jobs, one word: the in on line 3 is part of the for loop, which means "go through." The in on line 4 is the operator, which means "is it inside?" Same word, different jobs.
Trace word = "idea"
ch
ch in "aeiouAEIOU"
vowels
i
True
1
d
False
1
e
True
2
a
True
3
This is called the counting pattern: start a counter at 0, loop through every item, and add 1 only when an if is True. You can count anything this way: spaces, scores above 90, names that start with "A."
This is a pattern you will use all the time: loop through something and test each item. Run it with your name. The in on the for line walks through the letters. The in on the if line is a True or False question. Watch the badge on line 4 to see which letters pass.
Tips
Printing on one line with end=
Normally print() moves to a new line after it prints. You can change that with end=:
for i in range(1, 6):
print(i, end=" ")
1 2 3 4 5
end=" " puts a space after each value instead of a new line.
end=", " puts a comma and a space.
A plain print() after the loop ends the line, so the next output starts fresh.
How end= works
Every print adds something at the end. Normally that is a new line ("\n"). end= lets you replace it with anything else. end="" adds nothing at all, so values touch: 12345.
Why the extra print() after the loop? The last value was printed without a new line, so the cursor is still on the same line. Without that empty print(), the next output (Done!) would end up stuck to the numbers.
A comma problem:end=", " prints 1, 2, 3, 4, 5, with an extra comma at the end. Later you will learn ", ".join(...), which puts separators only between items.
print(x, end=" ") stays on the same line.
An empty print() moves to the next line.
end="" adds nothing after the value.
A list of numbers going straight down the screen gets long fast. With end equals a space, everything prints on one line. Try changing what is inside the quotes for end in the editor, like a comma or a dash.
The Big Idea
for or while?
Use a for loop when...
Use a while loop when...
you know how many times to repeat (range(10))
you do not know how many times (until the user gets it right)
you want to visit every item in a string or list
you repeat until something changes (lives reach 0)
Examples: print 1 to 100, check every letter, total every score
Examples: password check, a game loop, a menu that repeats until "quit"
Good for a for loop
scores = [88, 92, 75]
total = 0
for score in scores:
total += score
print("Total:", total)
Printing 1 to 5 works with both loops (you saw it on slide 2). When both work, prefer for: it is shorter and cannot become an infinite loop by accident.
A quick test: can you say how many times (or which items) before the loop starts? If yes, use for. If the answer is "it depends on what happens inside the loop," use while.
Known number of repeats or a sequence: for.
Repeat until a condition changes: while.
Know how many times or which items in advance? Use for.
Both loops repeat code, so how do you choose? Ask yourself: do I know how many times, or do I have a list to go through? Then use for. If you are waiting for something to happen, like the user typing quit, use while.
Debugging
Common mistakes
Mistake
Wrong code
What happens
Fix
Expecting the stop to be included
for i in range(1, 10): to print 1 to 10
No error. Prints 1 to 9 (off by one)
range(1, 11)
Expecting range to start at 1
for i in range(5):
No error. Prints 0 to 4
range(1, 6) if you want 1 to 5
Missing colon
for i in range(5)
SyntaxError: expected ':'
for i in range(5):
Missing in
for i range(5):
SyntaxError: invalid syntax
for i in range(5):
Body not indented
for i in range(5): print(i)
IndentationError: expected an indented block after 'for' statement on line 1
Indent the body 4 spaces
Looping over a plain number
for i in 5:
TypeError: 'int' object is not iterable
for i in range(5):
A decimal in range
range(2.5)
TypeError: 'float' object cannot be interpreted as an integer
Use whole numbers
Step of zero
range(1, 10, 0)
ValueError: range() arg 3 must not be zero
Use a step like 1 or -1
Counting down with a positive step
range(10, 0)
No error. The loop runs 0 times
range(10, 0, -1)
A number in a string
3 in "abc"
TypeError: 'in <string>' requires string as left operand, not int
"3" in "abc"
Error messages shown are from Python 3.13. Older versions word some messages a little differently.
Checking a range in 10 seconds
Most range bugs are "off by one": the loop runs one time too many or too few. Before you run a loop, check just two things:
First value: is the start what you want? (Remember the default is 0.)
Last value: is it one step before the stop? If you want to include a number, the stop must be past it.
If you are unsure, test with print(list(range(...))) to see every number the range makes.
"Not iterable" in an error means "you tried to loop over something that is not a sequence," like a plain number. Wrap the number in range().
The most common range mistakes give no error. Check the first and last values.
range needs whole numbers.
Check the first and last values of every range.
print(list(range(...))) shows the numbers.
The top two rows are the ones you will make most, and they give no error message. When your loop seems off, check two things: what number does it start on, and what number does it end on? Remember: start is in, stop is out.
Practice
Check yourself
Predict the answer, then click Check. This is practice only. Nothing is graded or recorded.
For each question:
Write out the numbers the range makes. Start is in, stop is out.
Count the iterations: that is how many times the body runs.
For strings, every character (including spaces) is one iteration.
For range: start is in, stop is out.
For strings: one character at a time. For lists: one item at a time.
Write out each range on paper before you choose an answer. For the in questions, ask yourself: is this a string, where chunks count, or a list, where only whole items count?
Know the key words: iteration, sequence, off-by-one, accumulator.
Let's wrap up. A for loop repeats once for each item in a sequence: a range, a string, or a list. range starts at 0 unless you say otherwise, and the stop is never included. And in does two jobs: it is part of the for loop, and it is an operator that answers True or False.