Most real programs need to repeat an action across many items — printing every name in a list, processing every row of a file, or checking every character in a string. Python's for loop is the primary tool for this: instead of manually indexing into a sequence, a for loop iterates directly over the items themselves, one at a time, until it runs out.

This is a different mental model from the "counter-based" for loops in languages like C or Java. Python's version is really a "for each" loop at heart — it hands you each item in turn, rather than making you manage an index variable yourself.

Basic Syntax: Iterating Over a List

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

for fruit in fruits:
    print(fruit)

Output:

apple
banana
cherry

Read this as "for each fruit in fruits, do the following." The variable fruit is created automatically by the loop and holds a different value from the list on each pass — you don't declare it separately beforehand.

Looping Over a String

Strings are iterable too — looping over one yields each character in turn:

for letter in "Python":
    print(letter)

Output:

P
y
t
h
o
n

Looping a Fixed Number of Times with range()

When you need to repeat something a specific number of times — rather than looping over an existing collection — use the built-in range() function, which generates a sequence of numbers on demand.

# range(5) generates 0, 1, 2, 3, 4 — it stops BEFORE the given number
for i in range(5):
    print(i)

print("---")

# range(start, stop) — stop is still exclusive
for i in range(2, 6):
    print(i)

Output:

0
1
2
3
4
---
2
3
4
5

A very common beginner mistake is expecting range(5) to include 5 — it doesn't. range(5) produces five numbers starting at 0, so the last one is 4. The full guide to range() covers its optional step argument and other details in depth.

Getting Both Index and Value with enumerate()

Sometimes you need the position of an item as well as the item itself — for example, to print a numbered list. Resist the temptation to manually track a counter variable; use enumerate() instead:

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

for index, fruit in enumerate(fruits):
    print(f"{index}: {fruit}")

# enumerate() also accepts a start value
for index, fruit in enumerate(fruits, start=1):
    print(f"{index}. {fruit}")

Output:

0: apple
1: banana
2: cherry
1. apple
2. banana
3. cherry

enumerate() hands back a pair (index, value) on every iteration, which the loop unpacks directly into two variables — much cleaner than manually incrementing a separate counter inside the loop body, and far less error-prone.

Looping Over a Dictionary

ages = {"Asha": 29, "Ravi": 34, "Meera": 25}

# Looping directly over a dict gives you its keys
for name in ages:
    print(name)

print("---")

# .items() gives you key-value pairs together
for name, age in ages.items():
    print(f"{name} is {age}")

Output:

Asha
Ravi
Meera
---
Asha is 29
Ravi is 34
Meera is 25

Once for loops feel natural, the next steps are learning how conditions interact with loops, and trying a real worked example that finds the largest number in a list using a for loop to see the pattern applied to an actual problem rather than just printed output.