Introduction
Python does not have a foreach keyword or function. The for loop in Python IS the foreach — it iterates directly over elements of any iterable (lists, tuples, dicts, sets, strings, generators) without needing an index. Where languages like PHP use foreach ($items as $item) or JavaScript uses items.forEach(callback), Python uses for item in items. This design is intentional — Python prefers a single, clear way to iterate.
Python's for Loop IS foreach
1# Python — this IS foreach
2fruits = ['apple', 'banana', 'cherry']
3for fruit in fruits:
4 print(fruit)
5# apple
6# banana
7# cherry
8
9# PHP equivalent
10# foreach ($fruits as $fruit) { echo $fruit; }
11
12# JavaScript equivalent
13# fruits.forEach(fruit => console.log(fruit));
14
15# Java equivalent
16# for (String fruit : fruits) { System.out.println(fruit); }
Iterating Over Different Types
1# List
2for item in [1, 2, 3]:
3 print(item)
4
5# Tuple
6for item in (1, 2, 3):
7 print(item)
8
9# String (iterates characters)
10for char in "hello":
11 print(char)
12
13# Set
14for item in {1, 2, 3}:
15 print(item)
16
17# Dictionary (iterates keys by default)
18data = {'a': 1, 'b': 2, 'c': 3}
19for key in data:
20 print(key, data[key])
21
22# Dictionary values
23for value in data.values():
24 print(value)
25
26# Dictionary key-value pairs
27for key, value in data.items():
28 print(f"{key} = {value}")
29
30# Range
31for i in range(5):
32 print(i) # 0, 1, 2, 3, 4
With Index (enumerate)
1fruits = ['apple', 'banana', 'cherry']
2
3# Need the index? Use enumerate
4for index, fruit in enumerate(fruits):
5 print(f"{index}: {fruit}")
6# 0: apple
7# 1: banana
8# 2: cherry
9
10# Start from a different index
11for index, fruit in enumerate(fruits, start=1):
12 print(f"{index}: {fruit}")
13# 1: apple
14# 2: banana
15# 3: cherry
Functional Alternatives
While Python prefers for loops, functional-style iteration exists:
1# map() — apply a function to each element
2numbers = [1, 2, 3, 4, 5]
3squares = list(map(lambda x: x ** 2, numbers))
4# [1, 4, 9, 16, 25]
5
6# filter() — keep elements matching a condition
7evens = list(filter(lambda x: x % 2 == 0, numbers))
8# [2, 4]
9
10# List comprehension — preferred over map/filter in Python
11squares = [x ** 2 for x in numbers]
12evens = [x for x in numbers if x % 2 == 0]
Simulating forEach with Side Effects
If you want to apply a function to each element (like JavaScript's forEach):
1# Using a for loop (Pythonic)
2items = ['a', 'b', 'c']
3for item in items:
4 process(item)
5
6# Using map with side effects (NOT recommended)
7# map() is lazy — must consume the iterator
8list(map(process, items)) # Works but unpythonic
9
10# Using a one-liner (not recommended for complex logic)
11[process(item) for item in items] # Creates unnecessary list
12
13# The correct way — just use a for loop
14for item in items:
15 process(item)
Iterating in Parallel (zip)
1names = ['Alice', 'Bob', 'Charlie']
2ages = [30, 25, 35]
3
4# Iterate two lists together
5for name, age in zip(names, ages):
6 print(f"{name} is {age}")
7
8# With three lists
9scores = [95, 87, 92]
10for name, age, score in zip(names, ages, scores):
11 print(f"{name}, age {age}, scored {score}")
12
13# zip stops at shortest — use zip_longest for uneven lists
14from itertools import zip_longest
15for a, b in zip_longest([1, 2, 3], [10, 20], fillvalue=0):
16 print(a, b) # (1,10), (2,20), (3,0)
1from itertools import chain, product, groupby
2
3# chain — iterate multiple iterables as one
4for item in chain([1, 2], [3, 4], [5]):
5 print(item) # 1, 2, 3, 4, 5
6
7# product — nested loops as a single iterator
8for x, y in product(range(3), range(3)):
9 print(f"({x}, {y})") # (0,0), (0,1), (0,2), (1,0), ...
10
11# groupby — group consecutive elements
12data = sorted([('A', 1), ('B', 2), ('A', 3)], key=lambda x: x[0])
13for key, group in groupby(data, key=lambda x: x[0]):
14 print(key, list(group)) # A [('A', 1), ('A', 3)], B [('B', 2)]
Why Python Doesn't Have foreach
Python follows the "there should be one obvious way to do it" philosophy. The for loop already handles every iteration use case:
for x in list — iterate elements
for i, x in enumerate(list) — iterate with index
for k, v in dict.items() — iterate key-value pairs
for a, b in zip(l1, l2) — iterate in parallel
Adding a separate foreach would be redundant.
Common Pitfalls
Modifying a list while iterating: for item in items: items.remove(item) skips elements because the list changes under the iterator. Iterate over a copy (for item in items[:]) or use list comprehension for filtering.
Using map() for side effects: map(print, items) is lazy — nothing prints until consumed. Use a for loop for side effects, not map() or list comprehension.
Forgetting that for over a dict iterates keys: for x in my_dict gives you keys, not values or key-value pairs. Use .values() or .items() for values or both.
Creating a list comprehension just for side effects: [send_email(u) for u in users] creates an unnecessary list of return values. Use a for loop instead.
Using range(len(list)) instead of enumerate: for i in range(len(items)): items[i] works but is less Pythonic and error-prone. Use for i, item in enumerate(items) instead.
Summary
Python's for item in iterable IS the foreach — no separate keyword or function exists
Use enumerate() when you need the index alongside the element
Use zip() to iterate multiple iterables in parallel
Prefer for loops over map() or list comprehensions for side effects
List comprehensions are the Pythonic alternative to map() and filter() for transformations