Баннер мобильный (3) Пройти тест

Itertools в Python: что это такое и как им пользоваться

Покоряем итераторы и комбинаторику со стандартным модулем Python

Инструменты

25 декабря 2025

Поделиться

Скопировано
Itertools в Python: что это такое и как им пользоваться

Содержание

    В разработке часто нужно работать с последовательностями и комбинациями данных. Например, с набором информации, которую человек ввел при регистрации, или с вычислениями. Такие данные объединяют в структуры. А для удобной работы с ними создают специальные инструменты.

    Один из таких инструментов в Python — модуль itertools. Это набор функций и итераторов для перебора коллекций. Что делает этот модуль и для чего нужен, рассказываем в статье.

    Что такое itertools и что стоит о нем знать

    У структур данных в Python есть общее название — коллекции. Это наборы информации: внутри одной переменной можно хранить несколько значений. К коллекциям, например, относятся списки или словари.

    В языке есть базовые команды и функции для работы с коллекциями. Но иногда их недостаточно: нужны более сложные действия. Например, разработчик хочет перебрать огромную коллекцию и провести операции только с некоторыми из ее значений. В таких случаях и помогает модуль под названием itertools.

    Itertools — это стандартный модуль языка для перебора коллекций, набор функций и итераторов для работы с ними. У него есть несколько особенностей:

    • Не работает с коллекциями напрямую. Вместо этого модуль возвращает итераторы — специальные переменные-счетчики. Благодаря такому подходу itertools экономит память и помогает не перегружать код.
    • Проводит ленивые вычисления. По-английски их называют lazy evaluation. Модуль вычисляет что-то не сразу, а только в момент, когда результат вычислений действительно нужен.
    • Написан на C. Не целиком, но многие его инструменты реализованы на этом языке. C известен скоростью и эффективностью работы, поэтому и itertools производит вычисления довольно быстро.
    • Хорошо масштабируется. Функции itertools легко адаптируются под большие объемы данных и крупные коллекции.

    Itertools вдохновлен функциональным программированием — подходом, принятым в языках вроде Haskell. Это заметно по особенностям его работы, например по тому, что он не работает с коллекциями напрямую.

    Чтобы добавить функции itertools в программу, сперва нужно импортировать модуль — написать в коде строку:

    import itertools

    Еще можно импортировать отдельные функции — это делается так:

    from itertools import <имя_функции>

    После этого нужным инструментом можно будет пользоваться в коде.

    Для чего используют itertools

    Модуль применяют, когда разработчику необходимо работать со структурами данных. Причем не просто, например, обратиться к какому-то элементу, а выполнить более сложное действие. Чаще всего это бывает нужно в таких ситуациях:

    • Работа с большими последовательностями. Например, с коллекциями, где сотни или даже тысячи элементов. Инструменты itertools способны обрабатывать такие объекты довольно быстро.
    • Обработка потоков данных. В таких ситуациях новая информация добавляется в коллекцию непрерывно, и обрабатывать ее нужно по мере поступления. Вообще, для потоков в Python есть свои инструменты, но иногда может пригодиться и itertools.
    • Замена вложенных циклов более читаемым кодом. Иногда, чтобы перебрать коллекцию напрямую, приходится использовать вложенные циклы: один цикл внутри другого. Это утяжеляет код и замедляет его работу, поэтому такие циклы предпочитают заменять на что-то другое, в том числе на некоторые функции из itertools.
    • Генерация комбинаций, перестановок, декартовых произведений. Это функции из математики и комбинаторики — Python часто используют для подобных вычислений. А в itertools есть немало инструментов, облегчающих работу с комбинаторными функциями. 
    • Работа с бесконечными последовательностями. Например, с числовыми рядами, арифметическими и геометрическими прогрессиями. В itertools есть функции для работы с ними, причем ими довольно легко пользоваться.

    Самые распространенные сценарии использования itertools — необходимость перебрать варианты или сгруппировать данные. Также модуль часто применяют, если нужно скомбинировать несколько объектов. А еще — при работе с техникой скользящего окна (​​Sliding Window).

    Техника скользящего окна — подход, когда из большой последовательности выделяют маленький подмассив. Его называют окном. Разработчик совершает с элементами внутри окна нужные действия, а затем смещает его в сторону, например на один элемент последовательности.

    Основные итераторы модуля itertools

    Итератором называют специальную переменную, которая нужна для подсчета и перебора какой-то коллекции. Если упростить, это — счетчик, число, которое указывает на номер элемента в ряду. Именно работа с итераторами лежит в основе модуля itertools в Python.

    Итераторы в модуле можно разделить на два типа: бесконечные и конечные. Вторые еще называют завершающимися по входным данным. Вот какие из них используют в разработке чаще всего.

    Бесконечные итераторы itertools: count(), cycle(), repeat()

    Такие итераторы указывают на значение в каком-то бесконечном ряду, например в прогрессии. Их особенность в том, что без ограничений извне они могут работать вечно — ведь и ряд, по которому они проходят, никогда не закончится.

    Чаще всего говорят о трех бесконечных итераторах — рассмотрим их подробнее.

    count(start = 0, step = 1). Эта функция генерирует бесконечную арифметическую прогрессию. На вход она принимает два параметра:

    • start — число, с которого должна начаться прогрессия, по умолчанию 0;
    • step — шаг прогрессии, по умолчанию 1.

    Например, count(0, 1) будет пошагово возвращать числа от 0 до бесконечности с шагом в единицу: 1, 2, 3, 4 и так далее.

    Числа, которые возвращает count(), часто используются в качестве итераторов в циклах. 

    Есть важный нюанс: работу этой функции всегда нужно ограничивать вручную. Например, с помощью команды break или islice() — в itertools есть такая функция, и мы поговорим о ней позже. Если не ограничить count(), он будет продолжать генерировать числа бесконечно и цикл никогда не закончится.

    Вот пример, как может работать itertools.count() в Python.

    # Импортируем нужную функцию
    from itertools import count 
    
    # Создаем цикл с помощью count(), начиная с 10 с шагом 2
    for i in count(10, 2):
        # Условие для остановки цикла — итератор стал больше 16
        if i > 16: 
            break 
        print(i)
    
    # Результат: 10 12 14 16
    

    cycle(iterable). Эта функция получает на вход коллекцию — параметр iterable. А затем бесконечно перебирает ее элементы. Чаще всего cycle() в Python переходит к следующему элементу, если ее установили как итератор в цикле. Но можно обойтись и без этого: просто прописать для нее команду next(cycle()).

    Чаще всего функцию используют, если нужно регулярно менять состояние объекта. Например, когда программируют какую-то бесконечную зацикленную анимацию. Вот как может выглядеть код с ее использованием:

    # Импортируем нужную функцию
    from itertools import cycle
    
    # Создаем cycle() из itertools и передаем ей простую коллекцию
    c = cycle(['A', 'B'])
    # Выводим на экран результат перебора в течение 5 шагов
    for i in range(5):
        print(next(c))
    
    # Результат: A B A B A

    repeat(object, times=None). Эта функция получает на вход объект и повторяет его. Если задать ей параметр times, она повторит объект указанное количество раз. А если не задавать — будет воспроизводить объект бесконечно.

    Вот пример того, как можно использовать repeat() в Python:

    # Импортируем функцию repeat()
    from itertools import repeat
    
    # Устанавливаем в качестве объекта число 7, количество повторов — 3
    list(repeat(7, 3))
    # Результат: [7, 7, 7]

    Итераторы, завершающиеся по входным данным

    Бесконечные итераторы могли работать сколько угодно раз. С конечными история другая. Их не нужно останавливать искусственно: они действуют в пределах длины входных данных. 

    Например, если дать такому итератору на вход коллекцию из 5 элементов, он переберет ее, дойдет до конца и остановится.

    Конечных итераторов больше, чем бесконечных, и используются они активнее. Давайте разберем основные из них.

    accumulate(iterable, func=operator.add). Этот итератор позволяет накапливать значения. Он проходит по какой-то коллекции и на каждом шаге запускает определенную функцию. По умолчанию это сумма — то есть accumulate() пошагово складывает значения элементов в коллекции.

    Часто accumulate() в Python используют, если нужно, например, подсчитать накопленные баллы в игре или тесте. Или в других ситуациях, когда перед разработчиком стоит задача получить новые значения из всех элементов коллекции. Вот пример:

    # Импортируем нужную функцию
    from itertools import accumulate
    
    # Накапливаем значения для списка из цифр 1, 2, 3, 4
    list(accumulate([1, 2, 3, 4]))
    
    # Результат: [1, 3, 6, 10]
    # Каждый элемент нового списка — сумма первых N чисел исходной коллекции 
    # Например, 3 — это сумма 1 и 2, а 6 — сумма 1, 2 и 3

    chain(*iterables). На вход этот итератор получает несколько итерируемых объектов — об этом говорит звездочка * в описании его синтаксиса. Затем он последовательно объединяет все объекты, которые ему передали.

    Чаще всего chain() в Python используют, если нужно слить несколько коллекций в одну. Ввести функцию проще, чем объединять списки или словари вручную. А код будет выглядеть аккуратнее.

    У chain() в itertools есть аналог: функция chain.from_iterable(). Разница только в том, что вторая функция получает на вход одну коллекцию из нескольких итерируемых объектов, например строк.

    Вот как можно использовать itertools.chain() в Python:

    # Импортируем chain()
    from itertools import chain
    
    # Объединяем с помощью chain() два списка
    list(chain([1, 2], [3, 4]))
    
    # Результат: [1, 2, 3, 4]

    islice(iterable, start, stop, step). Это аналог среза для итераторов — он как бы отбирает из последовательности определенный отрезок. На вход islice() в itertools принимает несколько переменных:

    • iterable — сам итерируемый объект;
    • start — начало отрезка;
    • stop — конец отрезка;
    • step — шаг, с которым функция будет выбирать значения для среза.

    Вот как можно использовать islice() в Python.

    # Импортируем islice()
    from itertools import islice
    
    # Отбираем отрезок из последовательности от 1 до 10
    # Начало отрезка — 2, конец — 8, шаг — 2 элемента
    list(islice(range(10), 2, 8, 2))
    
    # Результат: [2, 4, 6]

    tee(iterable, n = 2). Эта функция разделяет один итератор на несколько. По умолчанию — на два. Все созданные итераторы будут одинаковыми, но независимыми друг от друга. Важно помнить, что tee() в Python использует буферизацию, поэтому может потреблять память.

    Рассмотрим пример работы функции.

    # Импортируем tee()
    from itertools import tee
    
    # Создаем из одного итератора два и загружаем в переменные a и b
    a, b = tee([1, 2, 3])
    
    print(list(a), list(b))
    # Результат: [1, 2, 3] [1, 2, 3]

    Функции itertools для фильтрации и группировки

    В библиотеке itertools в Python много функций. В основном это инструменты, которые фильтруют, выделяют или группируют элементы коллекций. Если уметь с ними работать, взаимодействие с итерируемыми объектами становится заметно проще. Вот что это за функции.

    filterfalse(predicate, iterable). Это своего рода противоположность инструменту filter() для фильтрации элементов по определенному условию. Но если filter() отбирает элементы, которые соответствуют фильтру, то filterfalse() — наоборот. Вот пример:

    from itertools import filterfalse
    
    # Используем filterfalse, а в качестве условия берем остаток от деления на 2
    list(filterfalse(lambda x: x % 2, [1, 2, 3, 4]))
    
    # Результат: [2, 4] — только четные числа
    # Остаток от деления четных чисел на 2 равен 0, а 0 приравнивается к false

    takewhile(predicate, iterable). Получает на вход условие и итерируемый объект и, пока условие выполняется, отбирает из объекта элементы. Как только оно становится ложным хотя бы один раз, функция перестает выбирать новые элементы коллекции. Например:

    from itertools import takewhile
    
    # Ставим условие для takewhile() — значение элемента меньше 5
    list(takewhile(lambda x: x < 5, [1, 3, 5, 2]))
    
    # Результат: [1, 3]
    # После того как условие не выполнилось всего один раз, takewhile() остановился

    dropwhile(predicate, iterable). Эта функция обратна предыдущей — она не трогает элементы, пока условие истинно. Но как только оно хоть раз становится ложным, dropwhile() начинает отбирать все следующие значения. Например:

    from itertools import dropwhile
    
    # Ставим такое же условие — значение элемента меньше 5
    list(dropwhile(lambda x: x < 5, [1, 3, 5, 2]))
    
    # Результат: [5, 2]
    # Функция начала отбирать элементы, после того как условие один раз не выполнилось

    groupby(iterable, key=None). Эта функция группирует соседние элементы — создает из них набор пар. Первый элемент в паре — ключ, а второй — итератор по значениям с этим ключом.

    Не стоит путать groupby() из itertools с другими функциями Python с похожими названиями. Например, инструмент под именем groupby() есть во фреймворке Pandas, но он выполняет совсем другую задачу.

    Чаще всего ее используют для структур, где элементы уже отсортированы по какому-то принципу. Иначе похожие значения не будут соседними и не сгруппируются. Показываем, как может работать groupby() в Python:

    from itertools import groupby
    
    # Создаем строку, где все элементы отсортированы
    data = "AAABBBCC"
    
    # Группируем элементы строки с помощью groupby
    [(k, list(g)) for k, g in groupby(data)]
    
    # Результат: [('A', ['A','A','A']), ('B', ['B','B','B']), ('C', ['C','C'])]
    

    Комбинаторика в itertools: функции и как с ними работать

    В комбинаторике модуль используют особенно часто. Python традиционно используют для решения математических задач и вычислений, а в itertools уже реализованы основные операции комбинаторики.

    Декартово произведение в Python

    Вообще, это математическая операция. Но в программировании она бывает нужна не только для решения специфических задач. Ее можно использовать как аналог вложенных циклов, но более лаконичный и аккуратный.

    Для работы с декартовым произведением в Python есть функция product(*iterables, repeat=1). Она принимает на вход два параметра:

    • *iterables — произвольное количество итерируемых объектов;
    • repeat — количество повторений, по умолчанию 1.

    В itertools product() — это фактически альтернативный способ пройти по циклу с двумя и более переменными. Вот пример того, как функция может заменить собой вложенный цикл: 

    from itertools import product
    
    #Даем на вход функции product() два списка, каждый из двух элементов
    list(product([1, 2], ['a', 'b']))
    
    # Результат: [(1,'a'), (1,'b'), (2,'a'), (2,'b')]
    # То же самое получилось бы со вложенным циклом — по [1, 2] и [a, b]

    Перестановки

    Это комбинаторная операция, которая возвращает все возможные упорядоченные комбинации без повторений. Например, перестановок в ряду [1, 2] будет две: [1, 2] и [2, 1].

    Чтобы реализовать эту операцию, используют функцию Python permutations(iterable, r=None). На вход она получает какой-то итерируемый объект. Опционально к нему добавляют длину перестановки: по умолчанию она равна длине объекта.

    Например, если запустить перестановки для [1, 2, 3] с r = 2, получатся варианты комбинаций из двух элементов.

    Показываем, как работает permutations() в itertools, на примере:

    from itertools import permutations
    
    # Делаем перестановку по двум элементам для списка [1, 2, 3]
    list(permutations([1, 2, 3], 2))
    
    # Результат: [(1,2), (1,3), (2,1), (2,3), (3,1), (3,2)]

    Сочетания

    Это еще одна распространенная операция из комбинаторики, похожая на перестановки, но без упорядоченности. Поэтому возможных комбинаций меньше, чем с перестановками. В том же ряду [1, 2] сочетание будет только одно: [1, 2].

    В intertools для сочетаний используют функцию combinations(iterable, r). Как и с перестановками, она получает на вход итерируемый объект, а еще количество символов, из которых нужно сделать комбинацию. 

    У этой операции есть вариация — сочетания с повторениями. Для нее есть отдельная функция — combinations_with_replacement(). В целом она делает то же самое, но допускает, чтобы несколько элементов в комбинации были одинаковыми.

    Показываем, как работает combinations() в Python — без повторений и с ними:

    # Без повторений:
    
    from itertools import combinations
    
    # Находим возможные сочетания двух элементов из списка [1, 2, 3]
    list(combinations([1, 2, 3], 2))
    
    # Результат: [(1,2), (1,3), (2,3)]
    
    # С повторениями:
    
    from itertools import combinations_with_replacement
    
    list(combinations_with_replacement([1, 2], 2))
    
    # Результат: [(1,1), (1,2), (2,2)]

    С любыми комбинаторными функциями важно помнить одну вещь. Размер результатов может очень быстро расти. На коротких списках это незаметно, но если нужно найти комбинации, например, для коллекции из 25 элементов — количество вариантов уже может быть больше тысячи. 

    Так что пользоваться этими функциями нужно с осторожностью, иначе есть риск, что программа отнимет слишком много памяти.

    Itertools в Python — главное

    • itertools — инструмент для эффективной «ленивой» обработки структур данных. Лучше всего он подходит для больших последовательностей, потоковых данных или перебора вариантов.
    • Почти все функции возвращают итераторы — специальные переменные-счетчики. Они не хранят данные целиком в памяти, поэтому работают быстро и не отнимают много ресурсов.
    • В библиотеке есть бесконечные итераторы, которые требуют ручного ограничения. Иначе они могут никогда не остановиться.
    • С помощью itertools можно работать с комбинаторными функциями. Они быстро растут по размеру результата — используйте их с осторожностью.

    Инструменты

    Поделиться

    Скопировано
    0 комментариев
    Комментарии