for Loops
Most of the time you loop because you have a collection of things and want to do something with each one: print every student's name, add up every price, check every line of a file. Python's for loop is made for exactly this, and it is the loop you will write most often.
In this lesson you will loop over lists and strings, count with range(), get positions with enumerate(), walk two lists together with zip(), control loops with break, continue and else, and nest one loop inside another.
Looping over a collection
A for loop takes each item from a collection, one at a time, stores it in a loop variable, and runs the block for that item.
students = ["Aarav", "Priya", "Kabir", "Meera"]
for name in students:
print(f"Good morning, {name}!")
for letter in "Pune":
print(letter, end=" ")Good morning, Aarav! Good morning, Priya! Good morning, Kabir! Good morning, Meera! P u n e
Read the first loop as "for each name in students". You choose the loop variable's name, so pick one that describes a single item: name for students, price for prices. A string is a collection of characters, so the second loop visits each letter.
Any iterable works in a for loop. An iterable is anything that can hand out its items one by one: lists, strings, tuples, sets, dictionaries, files and more. You will learn how this works in Iterators & Generators.
Counting with range()
range() produces a sequence of whole numbers, which is how you repeat something a set number of times.
| Call | Numbers produced |
|---|---|
range(5) | 0, 1, 2, 3, 4 |
range(1, 6) | 1, 2, 3, 4, 5 |
range(10, 0, -2) | 10, 8, 6, 4, 2 |
The pattern is range(start, stop, step). The stop number is not included, just like slicing a string. start defaults to 0 and step to 1.
number = 7
for i in range(1, 11):
print(f"{number} x {i:>2} = {number * i:>2}")7 x 1 = 7 7 x 2 = 14 7 x 3 = 21 7 x 4 = 28 7 x 5 = 35 7 x 6 = 42 7 x 7 = 49 7 x 8 = 56 7 x 9 = 63 7 x 10 = 70
To get 1 to 10 you write range(1, 11). If you only need to repeat something and never use the number, name the variable _, a convention that means "I do not need this": for _ in range(3):.
Position and item with enumerate()
When you need the item and its position, wrap the collection in enumerate(). It gives you pairs of (position, item), and start=1 makes the count begin at 1, which suits lists shown to people.
toppers = ["Ananya", "Rohan", "Isha"]
for rank, name in enumerate(toppers, start=1):
print(f"{rank}. {name}")1. Ananya 2. Rohan 3. Isha
You may see for i in range(len(toppers)): followed by toppers[i] in older code or code ported from other languages. It works, but enumerate() is clearer and is the Python way.
Two lists together with zip()
zip() walks through two or more collections side by side, giving you one item from each on every pass.
items = ["Notebook", "Pen", "Geometry box"]
prices = [60, 15, 120]
quantities = [4, 3, 1]
total = 0
for item, price, qty in zip(items, prices, quantities, strict=True):
line = price * qty
total += line
print(f"{item:<13} {qty} x ₹{price:<4} = ₹{line}")
print(f"Total: ₹{total}")Notebook 4 x ₹60 = ₹240 Pen 3 x ₹15 = ₹45 Geometry box 1 x ₹120 = ₹120 Total: ₹405
By default, zip() stops quietly at the end of the shortest list, which can hide a missing value. Passing strict=True makes it raise a ValueError if the lists have different lengths, so a mistake is caught straight away.
break, continue and else
These work in for loops exactly as in while Loops: break leaves the loop, continue skips to the next item, and the loop's else block runs only if the loop finished without break.
trains = ["12951 Rajdhani", "12002 Shatabdi", "CANCELLED", "22439 Vande Bharat"]
wanted = "12002"
for train in trains:
if train == "CANCELLED":
continue
if train.startswith(wanted):
print("Found:", train)
break
else:
print("Train", wanted, "is not running today")Found: 12002 Shatabdi
Change wanted to "19019" and run it again. No break happens, so the else block reports that the train was not found.
Nested loops
A loop inside a loop runs the inner loop completely for every single pass of the outer loop. This is how you work with grids, tables and pairs.
rows = ["A", "B", "C"]
for row in rows:
for seat in range(1, 5):
print(f"{row}{seat}", end=" ")
print()A1 A2 A3 A4 B1 B2 B3 B4 C1 C2 C3 C4
The inner loop prints four seats on one line (end=" " keeps them together), and the empty print() after it ends the line. Three rows times four seats gives twelve seats. Be careful with nesting: a loop inside a loop over 10,000 items each is 100 million iterations.
Python also has handy helpers you can loop over: reversed(items) goes backwards and sorted(items) goes in order, both without changing the original list. Looping over dictionaries is covered in Dictionaries.
Common mistakes
- Changing a list while looping over it. Removing items from the list you are looping over makes Python skip items. Loop over a copy (
for m in marks[:]:) or build a new list instead, as you will learn in Comprehensions. - Forgetting that
range()stops early.range(1, 10)ends at 9. Writerange(1, 11)for 1 to 10. - Using
range(len(...))when you need items. Loop over the list directly, and useenumerate()when you also need the position. - Ignoring different lengths in
zip(). Withoutstrict=True, extra items are silently dropped.
Key points
for item in collection:runs the block once for each item in any iterable.range(start, stop, step)produces numbers;stopis not included.enumerate(items, start=1)gives position and item together.zip(a, b, strict=True)walks several collections in step and catches length mismatches.break,continueand the loopelsework the same way as inwhileloops.- Never add or remove items in a list while looping over that same list.
Exercise
Kabir's batting scores over six matches are [45, 0, 102, 33, 8, 76]. Using one for loop with enumerate(), print each match number and score, add up the total, count the half-centuries (50 or more), and skip printing for ducks (a score of 0) with continue. After the loop, print the total and the number of half-centuries.
Show solution
scores = [45, 0, 102, 33, 8, 76]
total = 0
fifties = 0
for match_no, runs in enumerate(scores, start=1):
total += runs
if runs >= 50:
fifties += 1
if runs == 0:
continue
print(f"Match {match_no}: {runs}")
print("Total runs:", total)
print("Fifty-plus scores:", fifties)Match 1: 45 Match 3: 102 Match 4: 33 Match 5: 8 Match 6: 76 Total runs: 264 Fifty-plus scores: 2
The total and count are updated before continue, so the duck still counts towards the totals but is not printed. enumerate() with start=1 gives match numbers that start at 1.
Quick Quiz
1. Which numbers does range(2, 8, 2) produce?
The step is 2 and the stop value 8 is not included.
2. What does enumerate(["a", "b"], start=1) give in a loop?
enumerate() produces pairs of position and item.
3. What does zip([1, 2, 3], ["x", "y"]) do with the extra 3?
Without strict=True, zip() stops quietly at the end of the shortest input.
4. When does the else block of a for loop run?
The loop else is skipped only when break ends the loop early.
Learn Python with a mentor
Free lessons get you started. Our Python Programming training adds real projects and code reviews from working developers.
- Project-based learning
- Mentor code reviews
- Free counselling call
