Функции для работы последовательностями

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

>>> good = ["Эльфы", "Люди", "Гномы", "Хоббиты",]
>>> "Орки" in good
False
>>> "Тролли" not in good
True

Так же операторы проверки вхождения работают и с другими комплексными типами. Например кортежами:

>>> t = tuple(["Эльфы", "Люди", "Гномы", "Хоббиты",])
>>> "Орки" in t
False
>>> "Гномы" in t
True

Или множествами:

>>> s = set(["Эльфы", "Люди", "Гномы", "Хоббиты",])
>>> "Орки" in s
False
>>> "Гномы" in s
True

Словари, поиск в данном случае идет по ключам:

>>> d = {"Хоббиты": "Шир", "Люди": "Сервер и Юг", "Эльфы": "Леса", "Гномы": "Подземелья"}
>>> "Орки" in d
False
>>> "Гномы" in d
True

И для полноты дам пример поиска по строке:

>>> st = "Гномы живут в Подземельях"
>>> "Орки" in st
False
>>> "Гномы" in st
True

Ленивый range

Мы пока очень несправедливо обходим стороной работу с функцией range в реальности она достаточно часто используется в работе. Но при обучении работе с последовательностями она просто незаменима. Эта функция умеет создавать последовательности простых чисел в заданном диапазоне и нужным шагом. Давайте напомню пример который приводился в разделе про списки:

>>> [i for i in range(10)]
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

То же самое можно получить с помощью вызова конструктора списка:

>>> list(range(10))
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

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

>>> r = range(10)
>>> type(r)
<class 'range'>
>>> r
range(0, 10)
>>> list(r)
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

Вместо того чтобы вернуть список от 0 до 9 функция range возвращает какой-то странный объект типа range. Дело в том, что в Python используется так называемые ленивые вычисления и объект range отдает следующее число тогда когда к нему обращаются за следующим значением. Давайте попробуем сделать действительно большой список:

>>> big = list(range(1000000))
>>> big = list(range(10000000))  
>>> big = list(range(100000000))

Видите, что с каждым увеличением порядка требуется все больше и больше времени на выполнение казалось бы безобидной строки. Если посмотреть на потребление ресурсов, то процесс python потребовал у операционной системы около 3 гигабайт оперативной памяти:

$ ps x -o rss,command | grep python
2723604 python
   812 grep --color=auto python

Мы взяли одной командой потратили огромное количество свободной памяти компьютера, при этом даже не начали делать ничего полезного! Как этого избежать? Для этих целей вместо того чтобы сразу занять все место Python создает объект типа range который работает следующим образом:

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

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

Встроенные функции для работы с последовательностями

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

Функция Описание Пример
len(iterable) Получить длину последовательности l = [1, 2, 3]; len(l)3
list([iterable]) Создать список на основе другой последовательности list('abc')['a', 'b', 'c']
enumerate([iterable], start=0) Генерирует кортежи состоящие из индекса элемента и самого элемента начиная со start list(enumerate(list('abc')))[(0, 'a'), (1, 'b'), (2, 'c')]
max(iterable, * [, key, default]) Найти элемент с максимальным значением 1 max([1, 2, 3, 4, 5])5
min(iterable, * [, key, default]) Найти элемент с минимальным значением 1 min([1, 2, 3, 4, 5])1
sum(iterable) Получить сумму всех элементов списка, список должен быть из чисел sum([2, 1, 3, 4, 7])17
any(iterable) Проверяет является ли истинной хотя бы один элемент списка 2 any(['', 0, None, False, 'ok'])True
all(iterable) Проверяет являются ли истинной все элементы списка 2 all(['', 0, None, False, 'ok'])False
range(stop) или range(start, stop, step) Создать список целых чисел от 0 до stop, можно указать начало start и шаг step list(range(5))[0, 1, 2, 3, 4]
reversed(iterable) Возвращает список в обратном порядке list(reversed(range(5)))[4, 3, 2, 1, 0]
map(fn, iterable) Применить функцию fn к каждому элементу списка и вернуть новый список list(map(str, range(5)))['0', '1', '2', '3', '4']
filter(fn, iterable) Применить функцию fn к каждому элементу и если она вернет True вернуть в новом списке list(filter(lambda x: x < 0, range(-5, 5)))[-5, -4, -3, -2, -1]
sorted(iterable) Получает на вход последовательность и сортирует ее sorted([23, 4, 42, 15, 16, 8])[4, 8, 15, 16, 23, 42]
slice(stop) или slice(start, stop[, step]) Возвращает объект slice, который можно использовать для получения элементов последовательности s=slice(1, 4); 'abcded'[s]'bcd'
zip(iterable, iterable) Получает на вход две последовательности и возвращает парой элементы обоих последовательностей list(zip([1, 2, 3], 'abc'))[(1, 'a'), (2, 'b'), (3, 'c')]

Дополнительные встроенные модули

Помимо этих функций в Python есть еще несколько модулей для работы с последовательностями. Если зайти на страницу со списком встроенных в стандартную библиотеку модулей то вы найдете следующие модули которые помогут в работе:

  • array - библиотека для работы с массивами, это списки принимающие только числа в качестве значений
  • collections - некоторые дополнительные виды контейнеров, например для организации цепочек или очередей
  • csv — модуль для чтения и записи табличных данных
  • dataclasses — специальный тип напоминающий словарь с предзаданными ключами
  • heapq — приоритизированые очереди, специальные списки в которых элементы хранятся в отсортированном виде
  • itertools — самый известный "неизвестный" модуль с большой коллекцией функций для перемешивания, преобразования, поиска и разных вычислений с последовательностями. Определенно следует добавить в обязательный список для изучения когда вы захотите поднять свой уровень владения языком
  • json — модуль для работы с данными в формате JSON, познакомимся с ним в этом курсе
  • xml — целая библиотека модулей для работы с файлами в формате XML

Ссылки


  1. Аргумент key ведет себя так же как в функции sort, на вход получает функцию которая будет использоваться для сравнения. 

  2. Напомню, что False считаются объекты со следующими значениями None, 0, 0.0, 0j, '', (), [], {}, остальные считаются True