Iterating with a for Loop in Python

Data Science Tool Box Mar 18, 2026

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() over iterrows()
  • 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 for loops and refactor them to use more Pythonic patterns with enumerate(), zip(), and direct iteration

Related Tutorials

Share:
Last updated: March 2026
Built-in Functions in Python 2026 str() in Python 2026: String Conversion + Modern Formatting & Best Practices memoryview with JAX in Python 2026: Zero-Copy NumPy → JAX Array Interop + Efficient ML Examples memoryview with TensorFlow in Python 2026: Zero-Copy NumPy → Tensor Interop + GPU Pinning & ML Examples memoryview with TensorFlow in Python 2026: Zero-Copy NumPy → Tensor Interop + ML Examples memoryview with NumPy & PyTorch in Python 2026: Zero-Copy Views, Efficient Slicing & ML Interop Examples memoryview with NumPy in Python 2026: Zero-Copy Views, Efficient Slicing & Real ML Examples memoryview() in Python 2026: Zero-Copy Magic for Large Binary Data + Real Examples import() in Python 2026: How It Works, Security Risks & Modern Alternatives (importlib) zip() in Python 2026: How to Use It, strict=True Behavior & Real-World Examples vars() in Python 2026: Accessing Object Namespace + Modern Introspection Patterns type() in Python 2026: Dynamic Type Inspection & Object Creation + Modern Patterns tuple() in Python 2026: Immutable Sequences + Modern Patterns & Best Practices super() in Python 2026: Method Resolution & Modern Inheritance Patterns sum() in Python 2026: Summing Iterables + Modern Numeric Patterns & Best Practices staticmethod() in Python 2026: Static Methods, Utility Functions & Modern Best Practices sorted() in Python 2026: Sorting Iterables + Modern Patterns & Best Practices slice() in Python 2026: Creating Slice Objects + Modern Patterns & Best Practices setattr() in Python 2026: Dynamic Attribute Setting + Modern Patterns & Safety set() in Python 2026: Mutable Sets Creation + Modern Patterns & Best Practices