What is a For Loop?
A for loop repeats a block of code for each item in a sequence. Think of it as an instruction: "For every item in this collection, do this." The loop automatically stops once every item has been processed.
The basic syntax is:
for variable in iterable:
# code to execute for each item
print(variable)
Here, variable takes the value of each item in the iterable one at a time. An iterable is anything Python can step through — lists, tuples, strings, ranges, dictionaries, files, and more.
Iterating Over Lists
The most common use of for is looping through a list:
fruits = ["apple", "banana", "cherry", "date"]
for fruit in fruits:
print(f"I like {fruit}")
print("Loop finished!")
You can also loop over a list of numbers and perform calculations:
scores = [88, 95, 72, 61, 99, 84]
total = 0
for score in scores:
total += score
average = total / len(scores)
print(f"Total: {total}")
print(f"Average: {average:.1f}")
Using range() with For Loops
The built-in range() function generates a sequence of numbers. It's extremely useful when you need to loop a specific number of times or work with indices.
| Syntax | Generates | Example |
|---|---|---|
range(n) | 0 to n-1 | range(5) → 0,1,2,3,4 |
range(start, stop) | start to stop-1 | range(2, 7) → 2,3,4,5,6 |
range(start, stop, step) | start to stop-1 by step | range(0, 10, 2) → 0,2,4,6,8 |
range(n, 0, -1) | Countdown | range(5, 0, -1) → 5,4,3,2,1 |
# Basic range - print 0 through 4
for i in range(5):
print(i, end=" ")
print() # newline
# Start and stop
for i in range(1, 6):
print(i, end=" ")
print()
# Step of 2 (even numbers)
for i in range(0, 11, 2):
print(i, end=" ")
print()
# Countdown using negative step
for i in range(10, 0, -1):
print(i, end=" ")
print("Blast off!")
range() does NOT create a list in memory — it generates numbers one at a time. This means range(1000000) uses almost no memory, making it perfect for large loops.
Iterating Over Strings
Strings are iterable — you can loop over each character:
word = "Python"
for char in word:
print(char, end="-")
print()
# Count vowels in a string
text = "Hello, World!"
vowels = "aeiouAEIOU"
count = 0
for char in text:
if char in vowels:
count += 1
print(f"Vowel count: {count}")
Iterating Over Dictionaries
When you loop over a dictionary directly, you iterate over its keys. Use .items() to get both key and value, .values() for just values, and .keys() for just keys (same as looping directly).
student = {
"name": "Alice",
"age": 20,
"grade": "A",
"major": "Computer Science"
}
# Loop over keys
print("Keys:")
for key in student:
print(f" {key}")
# Loop over values
print("\nValues:")
for value in student.values():
print(f" {value}")
# Loop over key-value pairs
print("\nKey-Value pairs:")
for key, value in student.items():
print(f" {key}: {value}")
enumerate() – Loop with Index
enumerate() is a built-in function that adds an automatic counter to any iterable. Instead of just getting the item, you get both the index and the item as a pair. This eliminates the need for a separate counter variable.
colors = ["red", "green", "blue", "yellow"]
# Without enumerate (old way)
for i in range(len(colors)):
print(f"{i}: {colors[i]}")
print()
# With enumerate (Pythonic way)
for index, color in enumerate(colors):
print(f"{index}: {color}")
print()
# Start counting from 1 instead of 0
for num, color in enumerate(colors, start=1):
print(f"Color #{num}: {color}")
Using enumerate() is considered more Pythonic than writing i = 0; i += 1 manually. It's cleaner and less error-prone. Use it whenever you need both the index and value from a sequence.
zip() – Loop Over Multiple Sequences
zip() lets you iterate over two or more sequences in parallel, pairing up elements at the same position. It stops at the shortest sequence.
names = ["Alice", "Bob", "Carol"]
scores = [95, 87, 92]
grades = ["A", "B+", "A-"]
# Pair up corresponding elements
for name, score, grade in zip(names, scores, grades):
print(f"{name}: {score} ({grade})")
print()
# zip() stops at the shortest sequence
letters = ["a", "b", "c", "d", "e"]
numbers = [1, 2, 3]
for letter, number in zip(letters, numbers):
print(f"{letter} → {number}")
You can combine zip() and enumerate() together:
students = ["Alice", "Bob", "Carol"]
marks = [88, 74, 95]
for i, (student, mark) in enumerate(zip(students, marks), start=1):
print(f"Rank {i}: {student} scored {mark}")
Nested For Loops
A nested loop is a loop inside another loop. The inner loop runs to completion for every single iteration of the outer loop. This is commonly used for working with 2D data, generating combinations, or building tables.
# Multiplication table (3x3)
for i in range(1, 4):
for j in range(1, 4):
print(f"{i} × {j} = {i*j}", end=" ")
print() # newline after each row
print()
# Nested loop over a list of lists (2D grid)
matrix = [
[1, 2, 3],
[4, 5, 6],
[7, 8, 9]
]
for row in matrix:
for element in row:
print(element, end="\t")
print()
While nested loops are useful, deeply nested loops (3+ levels) can slow your program dramatically and become hard to read. If you find yourself writing 3+ nested loops, consider refactoring into functions or using list comprehensions.
break and continue in For Loops
These two keywords give you fine-grained control over loop execution:
break— immediately exits the entire loopcontinue— skips the rest of the current iteration and moves to the next item
# break: stop when we find "banana"
fruits = ["apple", "cherry", "banana", "date", "elderberry"]
for fruit in fruits:
if fruit == "banana":
print(f"Found banana! Stopping search.")
break
print(f"Checked: {fruit}")
print()
# continue: skip even numbers, print only odds
for num in range(1, 11):
if num % 2 == 0:
continue # skip this number
print(num, end=" ")
print()
The for…else Clause
Python's for loop has an optional else block that runs only if the loop completed normally (without hitting a break). This is a unique Python feature useful for search patterns.
def find_item(items, target):
for item in items:
if item == target:
print(f"Found '{target}'!")
break
else:
# Only runs if break was never hit
print(f"'{target}' was not found in the list.")
inventory = ["keyboard", "mouse", "monitor", "webcam"]
find_item(inventory, "mouse") # Found!
find_item(inventory, "headset") # Not found
Sneak Peek: List Comprehensions
List comprehensions are a concise one-line way to build a list using a for loop. They're covered in full in the List Comprehensions lesson, but here's a quick taste:
# Traditional for loop to build a list
squares = []
for n in range(1, 6):
squares.append(n ** 2)
print(squares)
# Equivalent list comprehension (one line!)
squares = [n ** 2 for n in range(1, 6)]
print(squares)
# With condition: only even squares
even_squares = [n ** 2 for n in range(1, 11) if n % 2 == 0]
print(even_squares)
Practical Real-World Examples
# Example 1: Shopping cart total
cart = [
{"item": "Book", "price": 12.99, "qty": 2},
{"item": "Pen", "price": 1.49, "qty": 5},
{"item": "Notebook", "price": 4.99, "qty": 3},
]
total = 0
print("Receipt:")
print("-" * 35)
for product in cart:
subtotal = product["price"] * product["qty"]
total += subtotal
print(f" {product['item']:<12} x{product['qty']} ${subtotal:.2f}")
print("-" * 35)
print(f" {'TOTAL':<15} ${total:.2f}")
print()
# Example 2: Finding the maximum without max()
temperatures = [23, 17, 31, 28, 14, 35, 22]
highest = temperatures[0]
for temp in temperatures:
if temp > highest:
highest = temp
print(f"Highest temperature: {highest}°C")
🏋️ Practical Exercise
Write Python programs for each of the following:
- Use a
forloop withrange()to print the first 10 multiples of 7. - Given a list of words, use
enumerate()to print each word with its position number (starting at 1). - Given two lists —
citiesandpopulations— usezip()to print each city with its population. - Use a nested loop to print a 5×5 grid of asterisks (
*). - Write a loop that searches a list of names for a specific name and prints "Found!" or "Not found." using
for…else.
🔥 Challenge
Write a program that generates a simple number pyramid using nested loops:
1 1 2 1 2 3 1 2 3 4 1 2 3 4 5
Then modify it to reverse the pyramid (widest row first). Finally, use zip() to pair up a list of student names with their test scores and print a formatted leaderboard sorted by score (highest first — you may use sorted()).
Interview Questions on For Loops
- What is the difference between a
forloop and awhileloop? When would you use each? - What does
range(1, 10, 2)produce? What aboutrange(10, 0, -1)? - What is
enumerate()and why is it preferred over manually tracking an index? - How does
zip()behave when the two lists have different lengths? - What is the difference between
breakandcontinueinside a loop? - What does the
elseclause on aforloop do? When does it execute? - How would you iterate over a dictionary to access both keys and values simultaneously?
- What is the time complexity of nested loops? Give an example where O(n²) complexity appears.
📋 Summary
- The
forloop iterates over any iterable: lists, strings, ranges, dicts, tuples, and more. range(start, stop, step)generates integer sequences and is memory-efficient.- Iterating a dict directly yields keys; use
.items()for key-value pairs,.values()for values only. enumerate(iterable, start=0)provides both index and value — prefer it over manual counters.zip(a, b, ...)pairs elements from multiple iterables and stops at the shortest.- Nested loops run the inner loop completely for each iteration of the outer loop.
breakexits the entire loop;continueskips to the next iteration.- The
elseblock on aforloop only runs when the loop completes without abreak.
Related Topics
Frequently Asked Questions
You should not modify a list while iterating over it — this can cause items to be skipped or processed twice, leading to bugs. Instead, iterate over a copy of the list (for item in my_list[:]:) and modify the original, or collect changes and apply them after the loop.
range() returns a lazy range object that generates numbers on demand — it doesn't create all values in memory at once. list(range(5)) converts it to an actual list [0, 1, 2, 3, 4]. For loops, use range() directly as it's more memory-efficient.
Two common ways: for item in reversed(my_list): (lazy, no copy) or for item in my_list[::-1]: (creates a reversed copy). You can also use for i in range(len(my_list)-1, -1, -1): if you need the index too.
Python's for loop doesn't have a built-in counter, but enumerate() provides one elegantly. If you truly need C-style index-based looping (e.g., modifying elements in place), you can use for i in range(len(my_list)):, but this is generally not the Pythonic way.
An iterable is any object you can loop over (lists, strings, dicts, ranges). An iterator is an object that keeps track of its current position and returns the next value on each next() call. When you use a for loop, Python automatically calls iter() on the iterable to get an iterator, then calls next() repeatedly.