Iterating with a for Loop in Python
The for loop is one of the most frequently used constructs in data science. In 2026, writing clean, efficient, and Pythonic for loops is essential for processing data, training models, and building pipelines.
TL;DR — Modern for Loop Best Practices
- Use direct iteration over iterables instead of manual indexing
- Use
enumerate()when you need both index and value - Use
zip()when iterating over multiple sequences together - Avoid modifying a list while iterating over it
1. Basic and Pythonic for Loops
scores = [85, 92, 78, 95, 88]
# Good - direct iteration
for score in scores:
print(f"Score: {score}")
# Good - when you need the index
for i, score in enumerate(scores, start=1):
print(f"Rank {i}: {score}")
# Good - iterating over multiple lists together
names = ["Alice", "Bob", "Charlie"]
for name, score in zip(names, scores):
print(f"{name} scored {score}")
2. Real-World Data Science Examples
import pandas as pd
# Create a small demo file so this example runs as-is
# (in your project, sales_data.csv is your real export)
import numpy as np
rng = np.random.default_rng(42)
n = 60
pd.DataFrame({
"order_id": range(1001, 1001 + n),
"order_date": pd.date_range("2026-01-01", periods=n, freq="3D"),
"customer_id": rng.integers(101, 121, n),
"customer_name": rng.choice([" ana", "ben ", "chen", "dana"], n),
"product_id": rng.integers(1, 9, n),
"region": rng.choice(["North", "South", "East", "West"], n),
"category": rng.choice(["Electronics", "Computers", "Books", "Home"], n),
"payment_method": rng.choice(["card", "cash", "wallet"], n),
"segment": rng.choice(["consumer", "business"], n),
"quantity": rng.integers(1, 6, n),
"amount": rng.uniform(50, 2500, n).round(2),
"discount": rng.choice([0.0, 0.05, 0.1, 0.2], n),
}).assign(
price=lambda d: (d["amount"] / d["quantity"]).round(2),
profit=lambda d: (d["amount"] * rng.uniform(0.05, 0.3, n)).round(2),
).assign(
ship_date=lambda d: d["order_date"] + pd.Timedelta(days=2),
status=lambda d: np.where(d["amount"] > 2000, "priority", "standard"),
).to_csv("sales_data.csv", index=False)
df = pd.read_csv("sales_data.csv")
# Iterating over columns
for column in df.columns:
print(f"Processing column: {column} (dtype: {df[column].dtype})")
# Iterating over rows safely (for small datasets)
for idx, row in df.iterrows():
if row["amount"] > 1000:
print(f"High value order from {row['region']}")
# Better approach for most cases - vectorized or itertuples()
for row in df.itertuples():
if row.amount > 1000:
print(f"High value: {row.customer_id}")
3. Common Pitfalls to Avoid
# ❌ Bad: Modifying a list while iterating over it
numbers = [1, 2, 3, 4, 5]
for num in numbers:
if num % 2 == 0:
numbers.remove(num) # This can cause skipping elements!
# ✅ Better: Create a new list
numbers = [1, 2, 3, 4, 5]
even_numbers = [num for num in numbers if num % 2 == 0]
4. Best Practices in 2026
- Prefer iterating directly over the data (
for item in data) instead of using range + indexing - Use
enumerate()when you need the index - Use
zip()when iterating over multiple sequences in parallel - For large DataFrames, prefer vectorized operations or
itertuples()overiterrows() - Never modify the collection you are iterating over — create a new one instead
The Pythonic for Loop
Python's for loop iterates directly over items instead of over index numbers. Writing for value in values is shorter and less error-prone than for i in range(len(values)), and it works with any iterable, including files and generators.
When you also need the position, use enumerate. When you need items from two sequences together, use zip. When you need key and value from a dictionary, use .items().
For DataFrames, prefer vectorised column operations. When a loop is truly needed, itertuples() is much faster than iterrows() and returns rows with attribute access.
Worked Example: Index Loop versus Pythonic Loop
The same task is written with indexes and with the idiomatic tools.
products = ["pen", "notebook", "bag"]
prices = [1.5, 3.0, 25.0]
for i in range(len(products)):
print(i, products[i], prices[i])
for i, (name, price) in enumerate(zip(products, prices)):
print(i, name, price)
stock = {"pen": 100, "bag": 8}
for name, qty in stock.items():
print(f"{name}: {qty}")
Both loops print identical lines, but the second avoids manual indexing and cannot read past the end of either list. The dictionary loop reads key and value together without a second lookup.
Common Mistakes
- Using range(len(...)) when items are all you need.
- Modifying a list while looping over it.
- Looping over DataFrame rows where a vectorised operation exists.
- Using iterrows() for large frames instead of itertuples().
Quick Summary
- Loop over items directly.
- Use enumerate for positions and zip for pairs.
- Use .items() for dictionaries.
- Prefer vectorised pandas over row loops.
Conclusion
The for loop is a fundamental tool in data science. In 2026, writing Pythonic for loops means favoring direct iteration, using enumerate() and zip() when needed, and avoiding manual indexing. For performance-critical code with large DataFrames, prefer vectorized Pandas operations over explicit loops whenever possible.
Next steps:
- Review your current
forloops and refactor them to use more Pythonic patterns withenumerate(),zip(), and direct iteration