3.4. Встроенные возможности по работе с коллекциями

Здесь мы рассмотрим функции стандартной библиотеки itertools для обработки коллекций.

Встроенные возможности по работе с коллекциями

Мы уже знаем, что для работы с коллекциями в Python есть функции и методы. Однако часто требуется выполнить над коллекциями некоторые операции, которых нет в рассмотренных нами методах и функциях. Тогда на помощь приходят библиотеки (модули).

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

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

Чтобы получить доступ к функциям библиотеки, её необходимо подключить к своей программе (импортировать). Это можно сделать, используя ключевое слово import вместе с названием библиотеки. Импорт библиотек осуществляется в начале программы. После секции импорта следует оставить одну пустую строку по стандарту PEP 8. Пример импорта библиотеки itertools:

import itertools

Если теперь нам потребуется в этой библиотеке какая-то функция, например product(), то для её вызова нужно написать название библиотеки, поставить точку и написать название функции:

import itertools

print(itertools.product("ABC", repeat=2))

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

Можно импортировать функции из библиотек так, как если бы они стали частью нашей программы. Тогда следует указать ключевое слово from, затем название библиотеки, а после — import и через запятую указать названия функций, которые будут импортированы в нашу программу. При таком импорте вызов функций библиотеки осуществляется без указания названия библиотеки:

from itertools import product

print(product("ABC", repeat=2))

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

Для сохранения всех значений итератора его можно преобразовать в список с помощью функции list().

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

Функции библиотеки itertools можно разделить на следующие группы:

  • Функции, возвращающие бесконечные итераторы

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

count(start, step) — принимает на вход начальное значение (start, по умолчанию равно 0) и шаг (step, по умолчанию равен 1) бесконечно увеличивающейся числовой последовательности. В качестве значений аргументов можно использовать вещественные числа (float). Затем функция возвращает итератор, значения которого являются выходной последовательностью. Выведем числа от 0 до 1 с шагом 0.1. Так как возвращаемый итератор бесконечный, применим break для остановки цикла:

from itertools import count

for value in count(0, 0.1):
    if value <= 1:
        print(round(value, 1))
    else:
        break

Вывод программы:

0
0.1
0.2
0.3
0.4
0.5
0.6
0.7
0.8
0.9
1.0

cycle(iterable) — принимает на вход итерируемый объект, а возвращает итератор, который бесконечно циклически перебирает значения коллекции. Напишем программу, которая выводит строку длиной 10 символов, циклически перебирая символы входной строки ABC:

from itertools import cycle

max_len = 10
s = ""
for letter in cycle("ABC"):
    if len(s) < max_len:
        s += letter
    else:
        break
print(s)

Вывод программы:

ABCABCABCA

repeat(object, times) — возвращает итератор, повторяющий значение object (по умолчанию бесконечное количество раз — либо равно значению times). Напишем программу, которая создаст список из пяти строк ABC и выведет его на экран:

from itertools import repeat

result = list(repeat("ABC", 5))
print(result)

Вывод программы:

['ABC', 'ABC', 'ABC', 'ABC', 'ABC']
  • Функции, выполняющиеся до кратчайшей входной последовательности

accumulate(iterable) — возвращает итератор, состоящий из накопленных сумм элементов входной последовательности. Например,

from itertools import accumulate

for value in accumulate([1, 2, 3, 4, 5]):
    print(value)

Вывод программы:

1
3
6
10
15

chain(i_1, i_2, ..., i_n) — возвращает итератор, состоящий из элементов первого итерируемого объекта i_1, затем из второго i_2 и так далее до i_n. Пример:

from itertools import chain

values = list(chain("АБВ", "ГДЕЁ", "ЖЗИЙК"))
print(values)

Вывод программы:

['А', 'Б', 'В', 'Г', 'Д', 'Е', 'Ё', 'Ж', 'З', 'И', 'Й', 'К']

chain.from_iterable(iterable) — аналогична chain, но аргументом является один итерируемый объект, состоящий из итерируемых элементов. Пример:

from itertools import chain

values = list(chain.from_iterable(["АБВ", "ГДЕЁ", "ЖЗИЙК"]))
print(values)

Вывод программы:

['А', 'Б', 'В', 'Г', 'Д', 'Е', 'Ё', 'Ж', 'З', 'И', 'Й', 'К']
  • Функции для комбинаторики

product(i_1, i_2, ..., i_n, repeat) — возвращает итератор, значениями которого выступают элементы декартова произведения итерируемых объектов i_1, i_2, ..., i_n. Аргумент repeat определяет, сколько раз повторять в выходных комбинациях элементы каждого итерируемого объекта (значение по умолчанию 1). Элементами полученного итератора будут все возможные упорядоченные наборы элементов исходных итерируемых объектов. Пример:

from itertools import product

values = list(product([1, 2, 3], "АБВГ"))
print(values)

Вывод программы:

[(1, 'А'),
 (1, 'Б'),
 (1, 'В'),
 (1, 'Г'),
 (2, 'А'),
 (2, 'Б'),
 (2, 'В'),
 (2, 'Г'),
 (3, 'А'),
 (3, 'Б'),
 (3, 'В'),
 (3, 'Г')]

Тот же пример, но со значением repeat=2:

from itertools import product

values = list(product([1, 2, 3], "АБВГ", repeat=2))
print(values)

Вывод программы:

[(1, 'А', 1, 'А'),
 (1, 'А', 1, 'Б'),
 (1, 'А', 1, 'В'),
 (1, 'А', 1, 'Г'),
 (1, 'А', 2, 'А'),
 (1, 'А', 2, 'Б'),
 (1, 'А', 2, 'В'),
 (1, 'А', 2, 'Г'),
 (1, 'А', 3, 'А'),
 (1, 'А', 3, 'Б'),
 (1, 'А', 3, 'В'),
 (1, 'А', 3, 'Г'),
 (1, 'Б', 1, 'А'),
 (1, 'Б', 1, 'Б'),
 (1, 'Б', 1, 'В'),
 (1, 'Б', 1, 'Г'),
 (1, 'Б', 2, 'А'),
 (1, 'Б', 2, 'Б'),
 (1, 'Б', 2, 'В'),
 (1, 'Б', 2, 'Г'),
 (1, 'Б', 3, 'А'),
 (1, 'Б', 3, 'Б'),
 (1, 'Б', 3, 'В'),
 (1, 'Б', 3, 'Г'),
 (1, 'В', 1, 'А'),
 (1, 'В', 1, 'Б'),
 (1, 'В', 1, 'В'),
 (1, 'В', 1, 'Г'),
 (1, 'В', 2, 'А'),
 (1, 'В', 2, 'Б'),
 (1, 'В', 2, 'В'),
 (1, 'В', 2, 'Г'),
 (1, 'В', 3, 'А'),
 (1, 'В', 3, 'Б'),
 (1, 'В', 3, 'В'),
 (1, 'В', 3, 'Г'),
 (1, 'Г', 1, 'А'),
 (1, 'Г', 1, 'Б'),
 (1, 'Г', 1, 'В'),
 (1, 'Г', 1, 'Г'),
 (1, 'Г', 2, 'А'),
 (1, 'Г', 2, 'Б'),
 (1, 'Г', 2, 'В'),
 (1, 'Г', 2, 'Г'),
 (1, 'Г', 3, 'А'),
 (1, 'Г', 3, 'Б'),
 (1, 'Г', 3, 'В'),
 (1, 'Г', 3, 'Г'),
 (2, 'А', 1, 'А'),
 (2, 'А', 1, 'Б'),
 (2, 'А', 1, 'В'),
 (2, 'А', 1, 'Г'),
 (2, 'А', 2, 'А'),
 (2, 'А', 2, 'Б'),
 (2, 'А', 2, 'В'),
 (2, 'А', 2, 'Г'),
 (2, 'А', 3, 'А'),
 (2, 'А', 3, 'Б'),
 (2, 'А', 3, 'В'),
 (2, 'А', 3, 'Г'),
 (2, 'Б', 1, 'А'),
 (2, 'Б', 1, 'Б'),
 (2, 'Б', 1, 'В'),
 (2, 'Б', 1, 'Г'),
 (2, 'Б', 2, 'А'),
 (2, 'Б', 2, 'Б'),
 (2, 'Б', 2, 'В'),
 (2, 'Б', 2, 'Г'),
 (2, 'Б', 3, 'А'),
 (2, 'Б', 3, 'Б'),
 (2, 'Б', 3, 'В'),
 (2, 'Б', 3, 'Г'),
 (2, 'В', 1, 'А'),
 (2, 'В', 1, 'Б'),
 (2, 'В', 1, 'В'),
 (2, 'В', 1, 'Г'),
 (2, 'В', 2, 'А'),
 (2, 'В', 2, 'Б'),
 (2, 'В', 2, 'В'),
 (2, 'В', 2, 'Г'),
 (2, 'В', 3, 'А'),
 (2, 'В', 3, 'Б'),
 (2, 'В', 3, 'В'),
 (2, 'В', 3, 'Г'),
 (2, 'Г', 1, 'А'),
 (2, 'Г', 1, 'Б'),
 (2, 'Г', 1, 'В'),
 (2, 'Г', 1, 'Г'),
 (2, 'Г', 2, 'А'),
 (2, 'Г', 2, 'Б'),
 (2, 'Г', 2, 'В'),
 (2, 'Г', 2, 'Г'),
 (2, 'Г', 3, 'А'),
 (2, 'Г', 3, 'Б'),
 (2, 'Г', 3, 'В'),
 (2, 'Г', 3, 'Г'),
 (3, 'А', 1, 'А'),
 (3, 'А', 1, 'Б'),
 (3, 'А', 1, 'В'),
 (3, 'А', 1, 'Г'),
 (3, 'А', 2, 'А'),
 (3, 'А', 2, 'Б'),
 (3, 'А', 2, 'В'),
 (3, 'А', 2, 'Г'),
 (3, 'А', 3, 'А'),
 (3, 'А', 3, 'Б'),
 (3, 'А', 3, 'В'),
 (3, 'А', 3, 'Г'),
 (3, 'Б', 1, 'А'),
 (3, 'Б', 1, 'Б'),
 (3, 'Б', 1, 'В'),
 (3, 'Б', 1, 'Г'),
 (3, 'Б', 2, 'А'),
 (3, 'Б', 2, 'Б'),
 (3, 'Б', 2, 'В'),
 (3, 'Б', 2, 'Г'),
 (3, 'Б', 3, 'А'),
 (3, 'Б', 3, 'Б'),
 (3, 'Б', 3, 'В'),
 (3, 'Б', 3, 'Г'),
 (3, 'В', 1, 'А'),
 (3, 'В', 1, 'Б'),
 (3, 'В', 1, 'В'),
 (3, 'В', 1, 'Г'),
 (3, 'В', 2, 'А'),
 (3, 'В', 2, 'Б'),
 (3, 'В', 2, 'В'),
 (3, 'В', 2, 'Г'),
 (3, 'В', 3, 'А'),
 (3, 'В', 3, 'Б'),
 (3, 'В', 3, 'В'),
 (3, 'В', 3, 'Г'),
 (3, 'Г', 1, 'А'),
 (3, 'Г', 1, 'Б'),
 (3, 'Г', 1, 'В'),
 (3, 'Г', 1, 'Г'),
 (3, 'Г', 2, 'А'),
 (3, 'Г', 2, 'Б'),
 (3, 'Г', 2, 'В'),
 (3, 'Г', 2, 'Г'),
 (3, 'Г', 3, 'А'),
 (3, 'Г', 3, 'Б'),
 (3, 'Г', 3, 'В'),
 (3, 'Г', 3, 'Г')]

permutations(iterable, r) — возвращает итератор, значениями которого являются перестановки без повторений из элементов итерируемого объекта iterable. Если значение r не задано, элементы итератора имеют ту же длину, что и iterable. Иначе длина равна r. Пример:

from itertools import permutations

values = list(permutations("АБВ"))
print(values)

Вывод программы:

[('А', 'Б', 'В'),
 ('А', 'В', 'Б'),
 ('Б', 'А', 'В'),
 ('Б', 'В', 'А'),
 ('В', 'А', 'Б'),
 ('В', 'Б', 'А')]

combinations(iterable, r) — возвращает итератор, значениями которого выступают сочетания (без повторений) длиной r элементов итерируемого объекта iterable. Пример:

from itertools import combinations

values = list(combinations("АБВ", 2))
print(values)

Вывод программы:

[('А', 'Б'), ('А', 'В'), ('Б', 'В')]

combinations_with_replacement(iterable, r) — возвращает итератор, значениями которого выступают сочетания (с повторениями) длиной r элементов итерируемого объекта iterable. Пример:

from itertools import combinations_with_replacement

values = list(combinations_with_replacement("АБВ", 2))
print(values)

Вывод программы:

[('А', 'А'), ('А', 'Б'), ('А', 'В'), ('Б', 'Б'), ('Б', 'В'), ('В', 'В')]

Напоследок рассмотрим ещё пару полезных функций.

С одной из них мы познакомились ранее — функцией enumerate(). Она принимает на вход коллекцию, а возвращает итератор, значениями которого будут кортежи пар вида (номер элемента, значение элемента из коллекции). Можно дополнительно передать начало отсчёта номеров элементов (по умолчанию отсчёт идёт с 0). Пример:

for index, value in enumerate("ABC", 1):
    print(index, value)

Вывод программы:

1 A
2 B
3 C

Функция enumerate() применяется для прохода непосредственно по значениям коллекции, при этом предоставляется информация о номере каждого элемента.

Ещё одной полезной функцией является zip(). Эта функция принимает на вход коллекции, а возвращает итератор, значениями которого выступают кортежи, состоящие из элементов, имеющих одинаковые индексы, обрабатываемых коллекций. Пример:

print(list(zip("ABC", [1, 2, 3])))

Вывод программы:

[('A', 1), ('B', 2), ('C', 3)]

Коллекции могут иметь разное количество элементов, в таком случае zip() по умолчанию вернёт результат по самой короткой из них. Пример:

print(list(zip("ABCDE", [1, 2, 3])))

Вывод программы:

[('A', 1), ('B', 2), ('C', 3)]

Если в функции zip() задать значение аргумента strict=True, то в случае разной длины коллекций будет вызываться исключение ValueError:

print(list(zip("ABCDE", [1, 2, 3], strict=True)))

Вывод программы:

ValueError: zip() argument 2 is shorter than argument 1

Ещё по теме

Более подробно обо всех функциях модуля itertools можно почитать в документации.

Отмечайте параграфы как прочитанные чтобы видеть свой прогресс обучения

Вступайте в сообщество хендбука

Здесь можно найти единомышленников, экспертов и просто интересных собеседников. А ещё — получить помощь или поделиться знаниями.
Вступить
Сообщить об ошибке
Предыдущий параграф3.3. Списочные выражения. Модель памяти для типов языка Python

В этом параграфе мы поговорим о синтаксисе списочных выражений для обработки и создания коллекций и изучим примеры. А кроме того, обсудим итераторы (и их преимущества перед коллекциями) и разберёмся в отличиях изменяемых и неизменяемых типов данных.

Следующий параграф3.5. Потоковый ввод/вывод. Работа с текстовыми файлами. JSON

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