Ad – 728×90
🔀 Control Flow

Python For Loop – The Complete Guide

The for loop is one of the most powerful constructs in Python. It lets you iterate — walk through items one by one — over any sequence: a list, a string, a range of numbers, a dictionary, and much more. Whether you're processing hundreds of records, generating sequences, or building nested data structures, the for loop is your go-to tool. This lesson covers everything from the basics to advanced patterns including enumerate(), zip(), nested loops, and loop control with break and continue.

⏱️ 25 min read 🎯 Beginner–Intermediate 📅 Updated 2026

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:

Python
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:

Python
fruits = ["apple", "banana", "cherry", "date"]

for fruit in fruits:
    print(f"I like {fruit}")

print("Loop finished!")
▶ Output
I like apple I like banana I like cherry I like date Loop finished!

You can also loop over a list of numbers and perform calculations:

Python
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}")
▶ Output
Total: 499 Average: 83.2

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.

SyntaxGeneratesExample
range(n)0 to n-1range(5) → 0,1,2,3,4
range(start, stop)start to stop-1range(2, 7) → 2,3,4,5,6
range(start, stop, step)start to stop-1 by steprange(0, 10, 2) → 0,2,4,6,8
range(n, 0, -1)Countdownrange(5, 0, -1) → 5,4,3,2,1
Python
# 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!")
▶ Output
0 1 2 3 4 1 2 3 4 5 0 2 4 6 8 10 10 9 8 7 6 5 4 3 2 1 Blast off!
💡
range() is Memory Efficient

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:

Python
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}")
▶ Output
P-y-t-h-o-n- Vowel count: 3

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).

Python
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}")
▶ Output
Keys: name age grade major Values: Alice 20 A Computer Science Key-Value pairs: name: Alice age: 20 grade: A major: Computer Science
Ad – 336×280

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.

Python
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}")
▶ Output
0: red 1: green 2: blue 3: yellow 0: red 1: green 2: blue 3: yellow Color #1: red Color #2: green Color #3: blue Color #4: yellow
💡
Prefer enumerate() Over Manual Counters

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.

Python
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}")
▶ Output
Alice: 95 (A) Bob: 87 (B+) Carol: 92 (A-) a → 1 b → 2 c → 3

You can combine zip() and enumerate() together:

Python
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}")
▶ Output
Rank 1: Alice scored 88 Rank 2: Bob scored 74 Rank 3: Carol scored 95

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.

Python
# 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()
▶ Output
1 × 1 = 1 1 × 2 = 2 1 × 3 = 3 2 × 1 = 2 2 × 2 = 4 2 × 3 = 6 3 × 1 = 3 3 × 2 = 6 3 × 3 = 9 1 2 3 4 5 6 7 8 9
⚠️
Watch Out for Deep Nesting

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 loop
  • continue — skips the rest of the current iteration and moves to the next item
Python
# 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()
▶ Output
Checked: apple Checked: cherry Found banana! Stopping search. 1 3 5 7 9

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.

Python
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
▶ Output
Found 'mouse'! 'headset' was not found in the list.

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:

Python
# 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)
▶ Output
[1, 4, 9, 16, 25] [1, 4, 9, 16, 25] [4, 16, 36, 64, 100]

Practical Real-World Examples

Python
# 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")
▶ Output
Receipt: ----------------------------------- Book x2 $25.98 Pen x5 $7.45 Notebook x3 $14.97 ----------------------------------- TOTAL $48.40 Highest temperature: 35°C

🏋️ Practical Exercise

Write Python programs for each of the following:

  1. Use a for loop with range() to print the first 10 multiples of 7.
  2. Given a list of words, use enumerate() to print each word with its position number (starting at 1).
  3. Given two lists — cities and populations — use zip() to print each city with its population.
  4. Use a nested loop to print a 5×5 grid of asterisks (*).
  5. 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 for loop and a while loop? When would you use each?
  • What does range(1, 10, 2) produce? What about range(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 break and continue inside a loop?
  • What does the else clause on a for loop 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 for loop 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.
  • break exits the entire loop; continue skips to the next iteration.
  • The else block on a for loop only runs when the loop completes without a break.

Frequently Asked Questions

Can I change a list while iterating over it? +

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.

What is the difference between range() and list()? +

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.

How do I loop through a list in reverse? +

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.

Does Python's for loop have a traditional index counter like C? +

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.

What is an iterable vs an iterator in Python? +

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.