Как устроен список: элементы, append, pop, перебор и сортировка

Pythonобновлено 07.10.20269 мин чтенияесть тренажёр

Списки в Python хранят несколько значений под одним именем: оценки за четверть, имена друзей, очки игроков. Элементы стоят по порядку, у каждого есть номер-индекс, а список можно дополнять, сокращать и сортировать. Ниже — все основные приёмы с примерами и 6 задач с автопроверкой.

Загружаем…

Что такое списки в Python

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

marks = [5, 4, 5, 3, 5]
friends = ["Аня", "Миша", "Оля"]
empty = []
mixed = [7, "кот", True, 2.5]
print(marks)
print(len(friends))
[5, 4, 5, 3, 5]
3

Список marks содержит 5 оценок, friends — 3 имени, empty пока пуст, а mixed показывает, что в одном списке могут лежать значения разных типов. На практике так делают редко: удобнее, когда все элементы одного вида, — тогда их легко складывать, сравнивать и сортировать. Тип списка в Python называется list, и пустой список можно создать как [] или list().

Зачем вообще нужны списки в Python? Представьте программу, которая хранит оценки 25 учеников. Без списка понадобится 25 переменных и 25 одинаковых строк кода для подсчёта среднего. Со списком хватит одной переменной и короткого цикла. В школьной информатике эту структуру называют одномерным массивом: по федеральной образовательной программе массивы изучают в 9 классе[1], и в Python их роль выполняют именно списки.

Индексы: счёт с нуля и с конца

Индекс — это номер элемента в списке, и счёт в Python начинается с 0: первый элемент имеет индекс 0, второй — 1. Отрицательные индексы считают с конца: -1 — последний элемент, -2 — предпоследний.

planets = ["Меркурий", "Венера", "Земля", "Марс"]
print(planets[0])
print(planets[2])
print(planets[-1])
planets[3] = "Красная планета"
print(planets)
ЭлементМеркурийВенераЗемляМарс
Индекс слева0123
Индекс справа-4-3-2-1

Почему индексы списков в Python начинаются с нуля? Индекс показывает, на сколько шагов нужно отойти от начала: до первого элемента — 0 шагов. Так устроено большинство языков программирования, и к этому быстро привыкают. Последний индекс всегда на единицу меньше длины: в списке из 4 элементов это 3. Обращение к planets[4] вызовет ошибку IndexError — её разбор есть на странице об ошибке IndexError.

Через индекс элемент можно не только прочитать, но и заменить: planets[3] = "Красная планета" кладёт новое значение на место старого. Длина списка при этом не меняется.

Методы append, insert, remove и pop

Чтобы изменить состав списка, используют 4 главных метода: append добавляет в конец, insert — в нужное место, remove удаляет по значению, pop — по индексу. Методы вызываются через точку после имени списка.

МетодЧто делаетПримерСписок после
append(x)Добавляет x в конецa.append(9)[1, 2, 3, 9]
insert(i, x)Вставляет x на место ia.insert(0, 7)[7, 1, 2, 3]
remove(x)Удаляет первое найденное xa.remove(2)[1, 3]
pop()Удаляет и возвращает последнийa.pop()[1, 2]
pop(i)Удаляет и возвращает элемент ia.pop(0)[2, 3]

В таблице каждый пример выполняется для исходного списка a = [1, 2, 3]. Чаще всех нужен append: с его помощью список собирают по одному элементу, например из ввода пользователя.

backpack = []
backpack.append("тетрадь")
backpack.append("пенал")
backpack.insert(0, "учебник")
print(backpack)
taken = backpack.pop()
print("Достали:", taken)
backpack.remove("учебник")
print(backpack)

Важная деталь: метод remove удаляет только первое совпадение, а если значения нет совсем — выдаёт ошибку ValueError. Поэтому перед удалением полезно проверить if "учебник" in backpack:. Оператор in отвечает True или False на вопрос «есть ли такой элемент в списке». Методы append, insert, remove и pop меняют сам список и ничего нового не создают, поэтому писать backpack = backpack.append(...) нельзя: в переменной окажется None.

Длина и срезы списка

Функция len() возвращает количество элементов, а срез a[start:stop] — это новый список из части элементов: с индекса start до stop, не включая stop. Правило «правая граница не входит» здесь такое же, как у range.

week = ["пн", "вт", "ср", "чт", "пт", "сб", "вс"]
print(len(week))
print(week[0:5])
print(week[5:])
print(week[:3])
print(week[::2])
print(week[::-1])
7
['пн', 'вт', 'ср', 'чт', 'пт']
['сб', 'вс']
['пн', 'вт', 'ср']
['пн', 'ср', 'пт', 'вс']
['вс', 'сб', 'пт', 'чт', 'ср', 'вт', 'пн']

Если опустить начало среза, Python возьмёт элементы с самого первого, если опустить конец — до последнего включительно. Третье число — шаг: [::2] выбирает каждый второй элемент, а [::-1] переворачивает список. Срез никогда не вызывает IndexError: если границы выходят за пределы, он просто вернёт то, что есть, или пустой список. Это удобно, но иногда скрывает ошибку в расчёте индексов.

Перебор списка циклом for

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

prices = [120, 45, 300, 80]
for p in prices:
    print("Цена:", p)

for i in range(len(prices)):
    prices[i] = prices[i] * 2
print(prices)

В первом цикле переменная p получает сами значения, и изменить список через неё не выйдет: p = p * 2 поменяет только копию числа. Во втором цикле i пробегает индексы 0, 1, 2, 3, и запись prices[i] = ... меняет элементы на месте. Если нужны и номер, и значение, используйте enumerate(prices). Подробно о переборе последовательностей рассказано в уроке про цикл for.

Функции sum, min, max и sorted

Для числовых списков в Python есть 4 готовые функции: sum складывает элементы, min и max находят наименьший и наибольший, sorted возвращает новый отсортированный список. Они избавляют от ручных циклов в простых случаях.

scores = [7, 3, 9, 4]
print(sum(scores), min(scores), max(scores))
print(sorted(scores))
print(sorted(scores, reverse=True))
print(scores)
scores.sort()
print(scores)

Обратите внимание на разницу: sorted(scores) создаёт новый список и не трогает старый, а метод scores.sort() сортирует сам список и возвращает None. Строки сортируются по алфавиту, точнее по кодам символов, поэтому заглавные буквы окажутся раньше строчных. Среднее значение считают как sum(scores) / len(scores) — только если список не пустой, иначе будет деление на ноль. Все эти функции описаны в официальной документации Python[2], там же перечислены остальные методы списков.

Одна коробка, два имени

Если написать b = a, нового списка не появится — это 2 имени для одного и того же набора, и изменение через b будет видно через a. Чтобы получить независимую копию, нужен срез a[:] или метод a.copy().

a = [1, 2, 3]
b = a
b.append(4)
print(a)
c = a[:]
c.append(5)
print(a)
print(c)
[1, 2, 3, 4]
[1, 2, 3, 4]
[1, 2, 3, 4, 5]

Списки в Python изменяемые, а строки и числа — нет. Так это описано и в документации Python, в разделе о структурах данных. Поэтому с числами такой эффект не встречается: y = x; y = y + 1 не меняет x. Со списками же новички часто удивляются, что «испортился» исходный набор. Правило простое: присваивание не копирует, копию нужно сделать явно. Чем строки отличаются по поведению, разобрано в уроке про строки в Python.

Задачи на списки Python с автопроверкой

Чтобы закрепить приёмы, решите 6 задач в тренажёре вверху страницы: напишите код, нажмите «✓ Проверить», и решение запустится на нескольких тестах. Не прошедший тест покажет «Ожидалось» и «Получилось».

Во всех задачах числа или слова вводятся в одной строке через пробел, а input().split() превращает такую строку в набор слов. Для чисел добавьте list(map(int, ...)). Сначала попробуйте сами, затем откройте «Подсказку», а «Показать решение» оставьте на крайний случай. Самопроверка закрепляет материал лучше перечитывания — это подтвердило исследование Roediger и Karpicke[3], поэтому через пару дней вернитесь к задачам снова. Ещё 8 упражнений с разбором собраны на странице задач на списки.

Когда список не подходит

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

  • Телефонная книга на 100 контактов. Искать номер по имени удобнее в словаре: там доступ по ключу, а не перебор.
  • Набор из 1000 уникальных слов. Множество set само убирает повторы и быстрее отвечает на вопрос «есть ли слово».
  • Координаты точки из 2 чисел, которые не меняются. Подойдёт кортеж — неизменяемая пара (x, y).
  • Таблица на 10 000 строк с вычислениями. Для больших таблиц в профессиональной работе используют специальные библиотеки, а на школьном уровне хватит вложенных наборов.

«Индексы в Python начинаются с единицы, как в тетради». Это миф: первый элемент имеет индекс 0, и об этом прямо сказано в учебнике Python.

«b = a создаёт копию». Это не подтверждается запуском кода: обе переменные указывают на один объект, и изменение видно через оба имени.

Чего делать нельзя

Нельзя обращаться к элементу по индексу, равному длине: в наборе из 5 элементов последний индекс — 4. Остальные правила защищают от тихих ошибок.

  • Нельзя присваивать результат append обратно: a = a.append(1) превращает переменную в None.
  • Не следует удалять элементы во время перебора того же набора циклом for — часть элементов будет пропущена.
  • Не стоит называть переменную list: это имя встроенного типа, и после такой замены list() перестанет работать.
  • Не допускается считать среднее пустого набора без проверки длины — будет ZeroDivisionError.
  • Нельзя путать sort() и sorted(): первый возвращает None, второй — новый отсортированный набор.
  • Не стоит хранить в одном наборе числа и строки вперемешку, если их потом нужно сортировать: Python 3 не сравнивает число со строкой.

Правила именования переменных и оформления кода описаны в руководстве PEP 8[4]: имена в стиле snake_case, отступ 4 пробела. Python Software Foundation публикует это руководство вместе с документацией, а короткий пересказ — на странице про стиль кода Python.

Источники

[1] Приказ Минпросвещения России от 18.05.2023 № 370 «Об утверждении федеральной образовательной программы основного общего образования».

[2] The Python Tutorial (официальная документация Python 3). Python Software Foundation.

[3] Roediger H. L., Karpicke J. D. Test-enhanced learning: Taking memory tests improves long-term retention // Psychological Science. 2006. Vol. 17, № 3. P. 249–255.

[4] van Rossum G., Warsaw B., Coghlan N. PEP 8 — Style Guide for Python Code. Python Software Foundation, 2001.

Вопросы и ответы

Чем список отличается от массива?

В школьной информатике массивом называют набор однотипных элементов с номерами. В Python его роль играет list: он умеет то же самое и вдобавок может менять длину на ходу.

Как проверить, что набор пустой?

Сравните длину с нулём: if len(a) == 0:. Короче работает if not a: — пустой набор считается ложным значением.

Как превратить строку из ввода в числа?

Запись list(map(int, input().split())) делит строку по пробелам и превращает каждую часть в целое число. Если в строке есть буквы, будет ValueError.

Можно ли положить один набор внутрь другого?

Да, получится вложенная структура, например таблица: t = [[1, 2], [3, 4]]. К элементу обращаются двумя индексами: t[1][0] равно 3.

Как узнать, на каком месте стоит элемент?

Метод index(x) вернёт индекс первого совпадения. Если элемента нет, будет ошибка, поэтому сначала проверяйте x in a.

Почему print выводит элементы в квадратных скобках?

Так Python показывает весь набор целиком. Чтобы вывести элементы через пробел без скобок и кавычек, используйте ' '.join(...) для строк или цикл с print(x, end=' ').