itertools: функции для работы с итераторами
Модуль itertools в Python собирает функции, которые строят ленивые итераторы: бесконечные счетчики, склейку последовательностей, комбинации, перестановки и группировку. Ниже разобраны все основные функции с короткими примерами, а также новые pairwise() и batched(). Отдельно описаны ошибки, на которых чаще всего спотыкаются новички.
Python - один из самых популярных языков программирования благодаря своей простоте и гибкости. Одним из мощных инструментов, предоставляемых Python для работы с итерируемыми объектами, является модуль itertools. В этой статье мы рассмотрим основные методы модуля itertools python с примерами кода для лучшего понимания.

Содержание статьи
Что такое itertools?
Модуль itertools предоставляет набор функций для работы с итерируемыми объектами, позволяя эффективно создавать и обрабатывать итераторы. Он содержит множество полезных инструментов для комбинирования и манипулирования данными.
Назначение модуля itertools
Модуль itertools в Python предоставляет множество полезных инструментов для работы с итерируемыми объектами. Вот некоторые основные причины использования этого модуля:
- Эффективная обработка данных: Методы из
itertoolsпозволяют эффективно обрабатывать итерируемые объекты без необходимости создания дополнительных списков или кортежей. - Удобство в работе с последовательностями: Множество функций, таких как
chain(),zip_longest(),product(),permutations(), облегчают работу с различными комбинациями элементов из последовательностей. - Создание генераторов: Многие методы модуля можно использовать для создания генераторов, что позволяет экономить память при обработке больших объемов данных.
- Генерация комбинаций и перестановок:
itertoolsпредоставляет возможность генерировать комбинации, перестановки, а также другие комбинаторные объекты, что удобно при решении задач комбинаторики. - Управление итерациями: С помощью
itertoolsможно легко управлять итерациями, фильтровать данные на лету, а также выполнять другие операции без лишних затрат ресурсов. - Повышение производительности: Использование методов из
itertoolsможет улучшить производительность вашего кода за счет оптимизированных внутренних реализаций.
В целом, модуль itertools является мощным инструментом для работы с итерируемыми объектами в Python, который поможет вам упростить и оптимизировать обработку данных и выполнение различных операций над ними.
Некоторые основные методы itertools
В этом разделе: count(), cycle(), combinations(), chain(), permutations(), product().
1. count()
Метод count() создает бесконечную арифметическую прогрессию, начиная с указанного числа. Этот метод может использоваться для генерации целых чисел.
import itertools
for num in itertools.count(start=1, step=2):
if num > 10:
break
print(num)
2. cycle()
Метод cycle() бесконечно повторяет элементы из переданной коллекции.
import itertools
colors = ['red', 'green', 'blue']
color_cycle = itertools.cycle(colors)
for _ in range(5):
print(next(color_cycle))
3. combinations()
Метод combinations() генерирует все уникальные комбинации элементов указанной длины из переданной коллекции.
import itertools
letters = ['A', 'B', 'C']
comb = itertools.combinations(letters, 2)
for c in comb:
print(c)
4. chain()
Метод chain() объединяет несколько итерируемых объектов в один последовательный итератор.
import itertools
list1 = [1, 2, 3]
list2 = ['a', 'b', 'c']
chained_iter = itertools.chain(list1, list2)
for item in chained_iter:
print(item)
5. permutations()
Метод permutations() генерирует все возможные перестановки элементов указанной длины из переданной коллекции.
import itertools
numbers = [1, 2, 3]
perms = itertools.permutations(numbers, 2)
for p in perms:
print(p)
6. product()
Метод product() вычисляет декартово произведение нескольких итерируемых объектов.
import itertools
nums = [1, 2]
letters = ['a', 'b']
result = itertools.product(nums, letters)
for item in result:
print(item)
7. groupby()
Метод groupby() группирует элементы последовательности на основе общего ключа или функции.
import itertools
data = [('A', 1), ('B', 2), ('A', 3), ('C', 4)]
grouped_data = itertools.groupby(sorted(data), key=lambda x: x[0])
for key, group in grouped_data:
print(key, list(group))
8. islice()
Метод islice() позволяет создавать итератор, который представляет собой срез итерируемого объекта.
import itertools
nums = range(10)
sliced_nums = itertools.islice(nums, 2, 7)
for num in sliced_nums:
print(num)
9. tee()
Метод tee() создает несколько независимых итераторов из одного исходного итератора.
import itertools
nums = iter([1, 2, 3])
iter1, iter2 = itertools.tee(nums)
print(list(iter1)) # [1, 2, 3]
print(list(iter2)) # [1, 2, 3]
10. accumulate()
Метод accumulate() возвращает накопленные суммы или результаты функции для элементов итерируемого объекта.
import itertools
nums = [1, 2, 3, 4, 5]
acc_sums = itertools.accumulate(nums)
for sum_ in acc_sums:
print(sum_)
11. dropwhile()
Метод dropwhile() пропускает элементы из итерируемого объекта до тех пор, пока предикатная функция не возвращает False.
import itertools
nums = [1, 2, 3, 4, 5]
result = itertools.dropwhile(lambda x: x < 3, nums)
for num in result:
print(num)
12. takewhile()
Метод takewhile() возвращает элементы из итерируемого объекта до тех пор, пока предикатная функция возвращает True.
import itertools
nums = [1, 2, 3, 4, 5]
result = itertools.takewhile(lambda x: x < 3, nums)
for num in result:
print(num)
13. zip_longest()
Метод zip_longest() объединяет элементы из разных итерируемых объектов в кортежи, заполняя отсутствующие значения значением по умолчанию.
import itertools
nums = [1, 2, 3]
letters = ['a', 'b']
result = itertools.zip_longest(nums, letters, fillvalue='N/A')
for item in result:
print(item)
14. starmap()
Метод starmap() применяет функцию к последовательности значений, передавая каждое значение как аргументы функции.
import itertools
data = [(2, 3), (4, 5), (6, 7)]
result = itertools.starmap(lambda x, y: x * y, data)
for res in result:
print(res)
15. filterfalse()
Метод filterfalse() возвращает элементы итерируемого объекта, для которых предикатная функция возвращает False.
import itertools
nums = [1, 2, 3, 4, 5]
result = itertools.filterfalse(lambda x: x % 2 == 0, nums)
for num in result:
print(num)
16. compress()
Метод compress() фильтрует элементы итерируемого объекта на основе булевых значений из другого итерируемого объекта.
import itertools
data = ['a', 'b', 'c', 'd']
selectors = [True, False, True, False]
result = itertools.compress(data, selectors)
for item in result:
print(item)
17. count(start=0, step=1)
Метод count() создает бесконечную арифметическую прогрессию с заданным начальным значением и шагом.
import itertools
for num in itertools.count(start=1, step=2):
if num > 10:
break
print(num)
18. islice(iterable, stop)
Метод islice() создает итератор, который ограничен указанным числом элементов.
import itertools
nums = range(10)
sliced_nums = itertools.islice(nums, 5)
for num in sliced_nums:
print(num)
19. repeat(object, times=None)
Метод repeat() возвращает указанный объект заданное количество раз или бесконечно, если количество раз не указано.
import itertools
obj = 'Hello'
repeated_obj = itertools.repeat(obj, times=3)
for item in repeated_obj:
print(item)
20. chain.from_iterable()
Метод chain.from_iterable() объединяет элементы из итерируемых объектов, представленных как последовательность итераторов.
import itertools
nested_lists = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
flattened_list = itertools.chain.from_iterable(nested_lists)
for item in flattened_list:
print(item)
21. takewhile()
import itertools
nums = [1, 2, 3, 4, 5]
result = itertools.takewhile(lambda x: x < 3, nums)
for num in result:
print(num)
22. combinations_with_replacement()
Метод combinations_with_replacement() генерирует все уникальные комбинации элементов указанной длины из переданной коллекции с повторениями.
import itertools
colors = ['red', 'green', 'blue']
comb = itertools.combinations_with_replacement(colors, 2)
for c in comb:
print(c)
23. filterfalse()
import itertools
nums = [1, 2, 3, 4, 5]
result = itertools.filterfalse(lambda x: x % 2 == 0, nums)
for num in result:
print(num)
24. groupby()
import itertools
data = [('A', 1), ('B', 2), ('A', 3), ('C', 4)]
grouped_data = itertools.groupby(data, key=lambda x: x[0])
for key, group in grouped_data:
print(key, list(group))
Сводная таблица функций модуля
Функции itertools удобно делить на три группы. Все они возвращают итератор, поэтому результат нужно перебрать в цикле или передать в list().
| Группа | Функции | Для чего |
|---|---|---|
| Бесконечные | count, cycle, repeat | Счетчики, повтор значений по кругу |
| Конечные | accumulate, batched, chain, compress, dropwhile, filterfalse, groupby, islice, pairwise, starmap, takewhile, tee, zip_longest | Склейка, срезы, фильтрация, группировка |
| Комбинаторные | product, permutations, combinations, combinations_with_replacement | Перебор вариантов |
Встроенные zip(), map() и filter() к модулю не относятся, но работают в паре с ним. Подробнее о них в статье про zip и map, а о самом протоколе итерации на странице про итераторы.
Новые функции pairwise и batched
В последних версиях Python модуль пополнился двумя функциями, которые раньше приходилось писать вручную.
pairwise() для соседних пар
Функция появилась в Python 3.10 и выдает перекрывающиеся пары соседних элементов. Удобно для подсчета разниц между значениями.
from itertools import pairwise
prices = [100, 105, 98, 110]
print([b - a for a, b in pairwise(prices)])
# [5, -7, 12]batched() для разбиения на пачки
Функция добавлена в Python 3.12. Она режет последовательность на кортежи заданной длины, последний кортеж может быть короче. С Python 3.13 есть параметр strict=True, который вызывает ошибку при неполной последней пачке.
from itertools import batched
for chunk in batched(range(7), 3):
print(chunk)
# (0, 1, 2)
# (3, 4, 5)
# (6,)Типичные ошибки с itertools
Большинство проблем связано с тем, что итератор ленивый и одноразовый.
- Итератор нельзя пройти дважды: после первого
list()он пуст. Если данные нужны повторно, сохраните их в список или используйтеtee(). groupby()объединяет только идущие подряд элементы с одинаковым ключом. Перед группировкой данные сортируют по тому же ключу.print(itertools.chain(a, b))выводит объект, а не элементы. Оборачивайте результат вlist().count(),cycle()иrepeat()без ограничения дают бесконечный цикл. Ограничивайте их черезislice()или условие сbreak.
from itertools import groupby
words = ["apple", "bob", "avocado", "banana"]
words.sort(key=lambda w: w[0])
for letter, group in groupby(words, key=lambda w: w[0]):
print(letter, list(group))
# a ['apple', 'avocado']
# b ['bob', 'banana']Полный список функций и рецептов приведен в документации модуля itertools.
Частые вопросы
Ответы на вопросы, которые задают при первом знакомстве с модулем.
Нужно ли устанавливать itertools?
Нет, модуль входит в стандартную библиотеку. Достаточно написать import itertools или импортировать нужную функцию: from itertools import chain.
Чем combinations отличается от permutations?
combinations() не учитывает порядок: пара (1, 2) и (2, 1) считается одной. permutations() учитывает порядок и выдает обе пары. Для трех элементов по два получится 3 комбинации и 6 перестановок.
Как превратить список списков в плоский список?
Используйте list(chain.from_iterable(nested)). Это быстрее, чем сложение списков в цикле, и работает с любыми итерируемыми объектами внутри.
Почему groupby выдает одну и ту же группу несколько раз?
Функция группирует только соседние элементы. Если одинаковые ключи разбросаны по списку, отсортируйте его по ключу перед вызовом groupby().
Как получить первые N элементов генератора?
Вызовите islice(gen, n). Обычный срез gen[:n] для генераторов не работает и вызывает TypeError.