Python
list manipulation
chunking
programming tutorial
data processing

How to iterate over a list in chunks

Data Structures & Algorithms practice on Codemia

Step through 300 algorithm problems with animated visualisers that show the data structure changing as the code runs.

Practice algorithms

Introduction

Iterating over a list in chunks means processing a fixed number of elements at a time instead of handling the whole list at once. This is useful for batch API calls, pagination, memory-friendly processing, and any workflow where operating on smaller groups is clearer or safer than operating on one huge sequence.

The Basic Slicing Pattern

The most common Python pattern is a for loop with range and slicing:

python
1def chunked(values, size):
2    for start in range(0, len(values), size):
3        yield values[start:start + size]
4
5items = list(range(10))
6for chunk in chunked(items, 3):
7    print(chunk)

Output:

python
1[0, 1, 2]
2[3, 4, 5]
3[6, 7, 8]
4[9]

This is simple, readable, and works well for ordinary lists.

Why This Pattern Works

The call:

python
range(0, len(values), size)

produces starting indexes such as 0, 3, 6, and 9. Each slice then grabs at most size elements. Python slicing is forgiving, so the final chunk can be shorter without causing an index error.

That makes it a good general-purpose solution for list chunking.

Return A List Of Chunks Instead Of Iterating

If you want all chunks at once rather than an iterator, use a list comprehension:

python
1def chunk_list(values, size):
2    return [values[start:start + size] for start in range(0, len(values), size)]
3
4print(chunk_list([1, 2, 3, 4, 5], 2))

This is convenient for small to medium inputs, but remember that it creates the full nested list in memory immediately.

Chunk Any Iterable With itertools

Lists are easy because they support slicing. If you want a chunking function that works with any iterable, use itertools.islice:

python
1from itertools import islice
2
3def chunked_iterable(iterable, size):
4    iterator = iter(iterable)
5    while True:
6        chunk = list(islice(iterator, size))
7        if not chunk:
8            break
9        yield chunk
10
11for chunk in chunked_iterable(range(10), 4):
12    print(chunk)

This is useful when the input is a generator or a stream rather than a list already loaded in memory.

A Practical Batch API Example

Suppose an API accepts only 100 IDs per request:

python
1def fetch_batch(ids):
2    print("sending", ids)
3
4all_ids = list(range(1, 251))
5
6for batch in chunked(all_ids, 100):
7    fetch_batch(batch)

This pattern keeps the network contract explicit and avoids oversized requests.

Validate The Chunk Size

A chunk size of 0 or a negative value makes no sense and should be rejected:

python
1def chunked(values, size):
2    if size <= 0:
3        raise ValueError("size must be greater than 0")
4
5    for start in range(0, len(values), size):
6        yield values[start:start + size]

Adding this guard early prevents confusing behavior later.

Newer Python Convenience

In newer Python versions, itertools.batched provides a built-in chunking helper. If your environment has it, that can be a clean standard-library option. But the slicing or islice patterns are still worth knowing because they are easy to understand and work in older environments too.

Common Pitfalls

The biggest mistake is building a huge list of chunks when you really only need to process one chunk at a time. A generator-based approach is often better for large inputs.

Another common issue is forgetting to validate the chunk size. 0 and negative sizes usually indicate a bug upstream and should fail fast.

Developers also sometimes assume every chunk has exactly the same length. The final chunk is often shorter, and your downstream code should handle that normally.

Finally, do not overcomplicate chunking for plain lists. The range plus slicing pattern is already clear and efficient for many real-world Python tasks.

Summary

  • The standard list-chunking pattern is a loop over range with slicing.
  • Use a generator when you want to process chunks lazily.
  • Use itertools.islice when the input is a generic iterable instead of a list.
  • Validate that the chunk size is greater than zero.
  • Expect the final chunk to be shorter unless the list length divides evenly.

Related reading
Course
Intermediate
27 lessons
15 hours
DSA Fundamentals

Master algorithmic patterns and data structures through hands-on LeetCode-style problems - from arrays and hashing to dynamic programming and advanced graphs.

View the course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

Data Structures & Algorithms practice on Codemia

Step through 300 algorithm problems with animated visualisers that show the data structure changing as the code runs.

Practice algorithms

All Rights Reserved.