Iterating Over Iterables with next() – Understanding Iterators in Data Science 2026
The next() function is the core mechanism behind iteration in Python. Understanding how to use it directly with iterators gives you deeper control and is especially useful when working with large datasets, generators, and streaming data in data science.
TL;DR — How next() Works
next(iterator)returns the next item from an iterator- When the iterator is exhausted, it raises
StopIteration - You can provide a default value:
next(iterator, default)
1. Basic Usage of next()
numbers = [10, 20, 30, 40, 50]
# Create an iterator from an iterable
iterator = iter(numbers)
print(next(iterator)) # 10
print(next(iterator)) # 20
print(next(iterator)) # 30
# Get remaining items
remaining = list(iterator)
print(remaining) # [40, 50]
2. Safe Usage with Default Value
scores = [85, 92, 78]
iterator = iter(scores)
print(next(iterator, "No more scores")) # 85
print(next(iterator, "No more scores")) # 92
print(next(iterator, "No more scores")) # 78
print(next(iterator, "No more scores")) # "No more scores" (default)
3. Real-World Data Science Example
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")
# Using iterator to process large data row by row (memory efficient)
row_iterator = df.itertuples()
# Process first 5 rows manually using next()
for _ in range(5):
row = next(row_iterator)
print(f"Order {row.order_id}: ${row.amount:.2f}")
# Continue processing the rest with a for loop
for row in row_iterator:
if row.amount > 1000:
print(f"High value order: {row.order_id}")
4. Best Practices in 2026
- Use
next(iterator, default)to avoidStopIterationexceptions in production code - Prefer high-level constructs (
forloops, list comprehensions) over manualnext()calls when possible - Use
next()when you need fine-grained control over iteration (e.g., processing headers separately) - Remember that once you consume an iterator with
next(), you cannot go back unless you recreate it - For large DataFrames, prefer
itertuples()overiterrows()when using manual iteration
How next() Advances an Iterator
next(iterator) returns the following value and moves the iterator forward by one. When nothing is left, it raises StopIteration, unless you pass a default value as the second argument, which is returned instead.
This is useful for reading a header line before processing the rest of a file, taking the first matching item from a generator, or stepping through data manually while debugging.
Because next() changes the iterator's position, mixing manual next() calls with a for loop is fine: the loop simply continues from where next() stopped.
Worked Example: Header Rows and First Matches
We skip a header with next() and find the first matching value with a default.
lines = iter(["region,amount", "North,120", "South,80", "East,300"])
header = next(lines).split(",")
print("header:", header)
for line in lines:
region, amount = line.split(",")
print(region, int(amount))
amounts = [120, 80, 300]
first_big = next((a for a in amounts if a > 200), None)
first_huge = next((a for a in amounts if a > 1000), None)
print(first_big, first_huge)
After next() takes the header, the loop starts at the first data line. The generator search returns 300 for the first value above 200, and None when nothing exceeds 1000, instead of raising StopIteration.
Common Mistakes
- Calling next() on a list instead of an iterator.
- Forgetting the default and getting StopIteration.
- Using next() inside generators without handling the end.
- Losing an item by calling next() for a check and not using its value.
Quick Summary
- next() returns the next value and advances.
- Pass a default to avoid StopIteration.
- Use it to skip headers or find first matches.
- A for loop continues where next() stopped.
Conclusion
The next() function is the fundamental building block of iteration in Python. While you rarely need to call it directly in everyday data science work, understanding how it works helps you write more efficient code and better appreciate Python’s iteration protocol. Use next() when you need precise control, but prefer high-level iteration tools for most tasks.
Next steps:
- Experiment with manually iterating over a DataFrame using
itertuples()andnext()to better understand how Pandas iteration works under the hood