Зарегистрируйтесь для доступа к 15+ бесплатным курсам по программированию с тренажером

Модификация списков поэлементно Python: Списки

Как вы помните, элементы списков индексированы, то есть каждый элемент имеет порядковый номер. Первый элемент имеет индекс 0, последний — len(list) - 1.

Функция len возвращает длину списка, но работает она с различными типами, например — со строками и кортежами.

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

Последний элемент списка будет иметь отрицательный индекс -1. Увы, -0 использовать не получится. Вот пара примеров использования индексов со списком:

l = [0] * 3
l[0], l[1] = 10, 32
l[-1] = l[0] + l[1]
print(l)  # => [10, 32, 42]

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

pop и insert

Итак, получать и заменять элементы по одному мы умеем. Неплохо бы еще уметь удалять старые элементы и вставлять в середину списка новые. За это отвечают методы pop и insert соответственно. pop удаляет элемент по индексу.

Если не указать индекс, то удаляется последний элемент. При этом pop возвращает значение элемента, который удаляет:

l = [1, 2, 3]
l.pop()  # 3
print(l)  # => [1, 2]
l.pop(0)  # 1
print(l)  # => [2]

А вот пример использования insert:

l = [1, 2, 3]
l.insert(1, 100)
print(l)  # => [1, 100, 2, 3]
l.insert(-1, 200)
print(l)  # => [1, 100, 2, 200, 3]

insert всегда вставляет новый элемент перед элементом с указанным индексом относительно начала списка. При этом не важно, откуда мы индекс отсчитывали — от начала или от конца. И insert(-1, ..) вставляет элемент именно перед последним элементом.

Интересно, что l.insert(len(l), x) добавит элемент x в конец списка l, то есть сработает как l.append(x).

Фактически здесь не будет элемента, перед которым будет вставлен новый, вот новый элемент и попадет в конец списка.

Имейте в виду эту особенность, но используйте append, хотя бы потому, что его вызов проще читается.

Ошибки индексации

Если попытаться вызвать pop() у пустого списка или указать индекс за пределами индексов существующих элементов, вы получите ошибку IndexError:

l = []
l.pop()
# Traceback (most recent call last):
#   File "<stdin>", line 1, in <module>
# IndexError: pop from empty list

А вот insert более терпим к некорректным индексам и просто добавляет элементы с соответствующего края:

l = [0]
l.insert(-500, 1)
l.insert(1000, 2)
print(l)  # => [1, 0, 2]

Однако полагаться на это не стоит — индексы все же лучше держать под контролем.

Сортировка и разворачивание

Списки чего-либо периодически приходится сортировать, а иногда и разворачивать. Желательно уметь это делать эффективно. Поэтому список уже имеет встроенные средства для выполнения обеих задач — методы sort и reverse. Оба метода изменяют список по месту. Посмотрим на несколько примеров:

l = [1, 3, 7, 2, 10, 8]
l.sort()
print(l)  # => [1, 2, 3, 7, 8, 10]
l.reverse()
print(l)  # => [10, 8, 7, 3, 2, 1]

Эти методы могут работать без параметров. В случае reverse нечего и параметризовывать: разворачивание — это всегда разворачивание.

А вот сортировка может производиться по разным критериям. Если вызывать sort без параметров, то элементы сортируются в порядке возрастания. Однако методу можно передать параметр-функцию, которая будет возвращать критерий сортировки, то есть ключ.

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

def mod2(x):
    return x % 2

l = [1, 2, 3, 6, 5, 4]
l.sort(key=mod2)
print(l)  # => [2, 6, 4, 1, 3, 5]

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

Функция mod2 вернула для четных и нечетных чисел 0 и 1 соответственно. Поэтому в начале списка оказались сначала четные числа.

Интересно, что в пределах своей группы числа сохранили порядок: 6 шла в списке перед 4, и это взаимное расположение сохранилось.

Умение сохранить относительный порядок элементов, которые уже отсортированы относительно друг друга — важная характеристика алгоритма сортировки. Называется она стабильностью.

Сортировка в этом случае называется стабильной — и в Python сортировка именно такая.

Функция-ключ не обязана возвращать числа — она может возвращать любые значения, которые Python умеет сравнивать. Давайте в предыдущем примере усложним функцию-ключ:

def key(x):
    return (x % 2, x)

l = [1, 2, 3, 6, 5, 4]
l.sort(key=key)
print(l)  # => [2, 4, 6, 1, 3, 5]

Теперь числа разбиты на группы и при этом еще и отсортированы внутри групп. Когда Python сравнивает кортежи, он сравнивает сначала первые элементы, а если те равны — вторые и так далее.

Значения сравниваются, пока не найдется первое неравенство. Либо пока не кончится один из кортежей — в этом случае более короткий будет меньше. Вот несколько примеров:

print((1, 2, 3) < (1, 2, 4))  # => True
print((1, 1) < (1, 1, 1))  # => True
print((1, 2) > (1, 1, 1))  # => True
print((3, 4, 5) == (3, 4, 5))  # => True

Домашнее задание

В этом уроке мы показываем лишь общие принципы работы со списками. Мы не рассказали про методы count, remove, index: оставляем изучение этих методов вам.


Дополнительные материалы

  1. Стабильная сортировка

Аватары экспертов Хекслета

Остались вопросы? Задайте их в разделе «Обсуждение»

Вам ответят команда поддержки Хекслета или другие студенты.

Для полного доступа к курсу нужен базовый план

Базовый план откроет полный доступ ко всем курсам, упражнениям и урокам Хекслета, проектам и пожизненный доступ к теории пройденных уроков. Подписку можно отменить в любой момент.

Получить доступ
1000
упражнений
2000+
часов теории
3200
тестов

Открыть доступ

Курсы программирования для новичков и опытных разработчиков. Начните обучение бесплатно

  • 130 курсов, 2000+ часов теории
  • 1000 практических заданий в браузере
  • 360 000 студентов
Отправляя форму, вы принимаете «Соглашение об обработке персональных данных» и условия «Оферты», а также соглашаетесь с «Условиями использования»

Наши выпускники работают в компаниях:

Логотип компании Альфа Банк
Логотип компании Aviasales
Логотип компании Yandex
Логотип компании Tinkoff
Рекомендуемые программы

С нуля до разработчика. Возвращаем деньги, если не удалось найти работу.

Иконка программы Python-разработчик
Профессия
с нуля
Разработка веб-приложений на Django
2 февраля 10 месяцев

Используйте Хекслет по-максимуму!

  • Задавайте вопросы по уроку
  • Проверяйте знания в квизах
  • Проходите практику прямо в браузере
  • Отслеживайте свой прогресс

Зарегистрируйтесь или войдите в свой аккаунт

Отправляя форму, вы принимаете «Соглашение об обработке персональных данных» и условия «Оферты», а также соглашаетесь с «Условиями использования»