Пропустить до содержимого

Как использовать python itertools?

[

Итераторы в Python 3 с примерами

Что такое itertools и зачем его использовать?

Согласно документации, itertools это “модуль, который реализует ряд блоков построения итераторов, вдохновленных конструкциями из языков APL, Haskell и SML… Вместе они формируют “алгебру итераторов”, позволяющую создавать специализированные инструменты лаконично и эффективно на чистом Python”.

На практике это означает, что функции в itertools “работают” с итераторами, чтобы создавать более сложные итераторы. Рассмотрим, например, встроенную функцию zip(), которая принимает любое количество итерируемых объектов в качестве аргументов и возвращает итератор из кортежей с их соответствующими элементами:

Python

>>> list(zip([1, 2, 3], ['a', 'b', 'c']))
[(1, 'a'), (2, 'b'), (3, 'c')]

Как именно работает функция zip()?

Функция zip() берет по одному элементу из каждого из своих аргументов и создает кортеж из них. Затем эти кортежи добавляются в итоговый итератор. Этот процесс продолжается, пока есть элементы в каждом из исходных итераторов.

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

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

Рецепт “grouper”

Один из самых часто используемых рецептов itertools - это “grouper”. Он позволяет разбить последовательность на группы фиксированного размера.

Рассмотрим следующий пример:

Python

from itertools import zip_longest
def grouper(iterable, n, fillvalue=None):
args = [iter(iterable)] * n
return zip_longest(*args, fillvalue=fillvalue)
groups = grouper([1, 2, 3, 4, 5, 6, 7, 8], 3)
for group in groups:
print(group)

В этом примере мы определяем функцию grouper, которая принимает iterable, размер группы n и значение заполнителя (по умолчанию None). Функция использует множественное присваивание, чтобы создать несколько ссылок на один итератор, а затем использует функцию zip_longest, чтобы разделить элементы на группы заданного размера. Если элементов для формирования полной группы недостаточно, используется заполнитель.

На выходе мы получаем итератор groups, который перебирает группы по заданному размеру. В этом примере мы получим следующий результат:

Python

(1, 2, 3)
(4, 5, 6)
(7, 8, None)

Как вы можете видеть, последовательность [1, 2, 3, 4, 5, 6, 7, 8] разделена на группы по 3 элемента. Последняя группа содержит всего два элемента, и None используется в качестве заполнителя.

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


Последовательности чисел

Продолжим с использованием itertools для работы с последовательностями чисел.

Четные и нечетные числа

Рассмотрим задачу разделения последовательности чисел на четные и нечетные числа. Вместо использования циклов и условных операторов можно воспользоваться функцией islice из itertools.

Python

from itertools import count, islice
even_numbers = islice(filter(lambda x: x % 2 == 0, count()), 10)
odd_numbers = islice(filter(lambda x: x % 2 != 0, count()), 10)
print(list(even_numbers))
print(list(odd_numbers))

Подробностей достаточно сложно объяснить без поддержки закодированного кода. Но суть кода такова:

  • count() создает бесконечную последовательность чисел
  • Функции filter() и lambda используются для фильтрации четных и нечетных чисел
  • Функция islice() ограничивает количество элементов в каждой последовательности до 10

На выходе мы получаем следующий результат:

Python

[0, 2, 4, 6, 8, 10, 12, 14, 16, 18]
[1, 3, 5, 7, 9, 11, 13, 15, 17, 19]

Обратите внимание, что используется только один цикл count(), а остальные операции выполняются с помощью itertools.

Рекуррентные последовательности

Другой интересный пример использования itertools - это работа с рекуррентными последовательностями.

Давайте рассмотрим последовательность Фибоначчи:

Python

from itertools import islice
def fibonacci():
a, b = 0, 1
while True:
yield a
a, b = b, a + b
fib = islice(fibonacci(), 10)
print(list(fib))

В этом примере определена функция fibonacci(), которая является генератором для последовательности Фибоначчи. Функция использует множественное присваивание, чтобы обновлять значения a и b на каждой итерации. Последовательность Фибоначчи продолжается бесконечно, поэтому мы ограничиваем результат до 10 элементов при помощи функции islice().

На выходе мы получим следующий результат:

Python

[0, 1, 1, 2, 3, 5, 8, 13, 21, 34]

В этом примере мы видим, как можно эффективно создавать бесконечные рекуррентные последовательности с использованием itertools.


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