Python itertools.batched: разбить список на части
itertools.batched() делит iterable на кортежи заданного размера и появился в Python 3.12. Последняя группа может быть короче, а пустой вход не даёт ни одной группы. Функция работает лениво: читает элементы по мере запроса и не копирует весь список целиком.
Разбить список на группы по три
from itertools import batched
items = [1, 2, 3, 4, 5, 6, 7]
chunks = list(batched(items, 3))
print(chunks) # [(1, 2, 3), (4, 5, 6), (7,)]Размер группы должен быть положительным целым числом. batched() возвращает кортежи, а не списки, поэтому не пытайтесь изменить группу на месте. Если нужен другой тип, преобразуйте явно: [list(chunk) for chunk in batched(items, 3)].
В отличие от нарезки items[i:i + 3], batched() принимает любой iterable, включая генератор и файловый объект. Это удобно для потоковой обработки: в памяти находится только текущая группа, а не весь набор.
Проверить аргумент и обработать ошибку
from itertools import batched
try:
list(batched([1, 2], 0))
except ValueError as exc:
print(exc) # n must be at least oneНулевой или отрицательный размер вызывает ValueError при первом обращении к итератору, а не при создании объекта. Отрицательное число не означает «взять с конца». Для больших батчей учитывайте, что группа всё равно материализуется в кортеж: миллион элементов с n=1_000_000 займёт много памяти.
На Python 3.10 и 3.11 используйте рецепт с itertools.islice:
from itertools import islice
def batched(iterable, n):
iterator = iter(iterable)
while chunk := tuple(islice(iterator, n)):
yield chunkПроверьте, что n > 0, если функция принимает размер из конфигурации. Для асинхронных источников itertools.batched() не подходит: он работает с обычными синхронными итераторами.
Документация: itertools.batched, рецепты itertools.