Split a Python list into chunks

Use slicing or itertools.batched to process fixed-size groups, validate the chunk size, and distinguish chunk size from number of chunks.

Best practices
Python programming and application logging

For a list, use slices stepped by the desired chunk size. For an arbitrary iterable on Python 3.12 or later, itertools.batched() yields tuples lazily. In both cases, the final group may be shorter.

Split a list with slices

items = list(range(1, 11))
size = 3
if size < 1:
    raise ValueError("Chunk size must be positive")

chunks = [items[index:index + size] for index in range(0, len(items), size)]
print(chunks)  # [[1, 2, 3], [4, 5, 6], [7, 8, 9], [10]]

The chunk size must be a positive integer. A zero step raises an error, and a negative step can silently produce no chunks with this range. Validate the size before using it.

Slices create new lists, but their elements are references to the same objects. Mutating a nested object through a chunk can therefore affect the original data.

Use itertools.batched

from itertools import batched

for chunk in batched(range(1, 11), 3):
    print(chunk)
# (1, 2, 3), (4, 5, 6), (7, 8, 9), (10,) on separate lines

batched was added in Python 3.12. Python 3.13 added strict=True, which raises ValueError if the final batch is incomplete. Without strict mode, the final shorter batch is returned normally. Lazy batching avoids constructing every batch up front, but does not remove memory already occupied by an input list.

Yield list slices with a generator

def chunked(items, size):
    if size < 1:
        raise ValueError("Chunk size must be positive")
    for index in range(0, len(items), size):
        yield items[index:index + size]

for chunk in chunked(list(range(10)), 3):
    print(chunk)

This helper requires a sized, sliceable input. Its body, including validation, runs when iteration begins. It is useful for a consumer that expects lists, such as a database batch-writing function. Replace the print call with the consumer, and define how failures and retries should behave if earlier batches have already succeeded.

FAQ

What if the size exceeds the input length? A nonempty list produces one shorter chunk. An empty list produces no chunks, provided the size is valid.

Does this pad the last chunk? No. Add explicit padding only if the consumer requires it and has a defined way to distinguish padding from real data.

How does numpy.array_split differ? Passing an integer to numpy.array_split(array, count) asks for that many approximately equal sections, not sections containing that many items. Do not substitute the two operations without checking which quantity you mean.

References

Get a tailored plan

Contact us

Join the community

Scan with WeChat
to join the community

Try Guance

Start online and pay only for what you use.

Get started

Choose a Guance plan

Code hosting