Глиф Учебники

Урок 6. Списки

Курс «Python» · урок 6 из 10 · 4 минуты чтения

Когда значений много — отметки за четверть, список покупок, результаты измерений, — заводить переменную на каждое неудобно. Их хранят в списке: одна переменная, а в ней сколько угодно значений по порядку. Список в Python — то же, что массив в Pascal, только его размер не задают заранее: он растёт и уменьшается сам.

Создание списка

Список записывают в квадратных скобках через запятую:

Python
marks = [8, 9, 7, 10]
names = ["Аня", "Борис", "Вика"]
empty = []
print(marks)
print(len(names))
print(len(empty))
Вывод
[8, 9, 7, 10]
3
0

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

Индексы

У каждого элемента есть номер — индекс. Нумерация начинается с нуля: первый элемент — [0], второй — [1]. Отрицательный индекс считает с конца: [-1] — последний элемент.

с начала с конца names [0] [1] [2] "Аня" "Борис" "Вика" [-3] [-2] [-1] [3] нет такого IndexError
Индексы списка names идут с нуля: у первого элемента индекс 0, у последнего ещё и индекс −1, а индекса 3 в списке из трёх элементов нет — обращение к нему даёт IndexError.
Python
names = ["Аня", "Борис", "Вика"]
print(names[0])
print(names[2])
print(names[-1])
names[1] = "Глеб"
print(names)
Вывод
Аня
Вика
Вика
['Аня', 'Глеб', 'Вика']

Элемент можно заменить, присвоив новое значение по индексу. Если обратиться к индексу, которого нет (в списке из трёх элементов — names[3]), программа остановится с ошибкой:

Текст
IndexError: list index out of range

Добавление и удаление

Команды, которые пишут через точку после имени списка (a.append(x)), называются методами: это функции, которые работают с этим списком.

ЗаписьЧто делает
a.append(x)добавляет x в конец
a.insert(i, x)вставляет x перед элементом с индексом i
a.remove(x)удаляет первый элемент, равный x
a.pop()удаляет последний элемент и возвращает его
a.pop(i)удаляет элемент с индексом i и возвращает его
del a[i]удаляет элемент с индексом i
x in aTrue, если x есть в списке
Python
items = ["хлеб", "молоко"]
items.append("сыр")
items.insert(0, "вода")
print(items)
items.remove("молоко")
last = items.pop()
print(last)
print(items)
print("хлеб" in items)
Вывод
['вода', 'хлеб', 'молоко', 'сыр']
сыр
['вода', 'хлеб']
True

remove для значения, которого нет в списке, выдаёт ошибку ValueError. Если не уверены, проверьте заранее: if x in items: items.remove(x).

Перебор списка

Цикл for проходит по элементам по очереди. Если нужен и номер, и значение, помогает enumerate:

Python
marks = [8, 9, 7]
for m in marks:
    print(m, end=" ")
print()
for i, m in enumerate(marks, start=1):
    print(i, "—", m)
Вывод
8 9 7
1 — 8
2 — 9
3 — 7

start=1 — с какого числа начинать нумерацию; без него счёт идёт с 0.

Сумма, наименьшее, наибольшее, среднее

Python
marks = [8, 9, 7, 10, 6]
print(sum(marks))
print(min(marks), max(marks))
print(sum(marks) / len(marks))
Вывод
40
6 10
8.0

Среднее — сумма, делённая на количество. Если список может быть пустым, проверьте это до деления: на ноль делить нельзя.

Срезы

Срез — часть списка: a[начало:конец]. Как и в range, конец не входит. Пропущенное начало значит «с самого начала», пропущенный конец — «до самого конца».

Python
nums = [10, 20, 30, 40, 50]
print(nums[1:3])
print(nums[:2])
print(nums[2:])
print(nums[::-1])
Вывод
[20, 30]
[10, 20]
[30, 40, 50]
[50, 40, 30, 20, 10]
индекс 0 1 2 3 4 nums[1:3] 10 20 30 40 50 [20, 30] nums[:2] 10 20 30 40 50 [10, 20] nums[2:] 10 20 30 40 50 [30, 40, 50] конец среза — в срез не входит
Срез берёт элементы от индекса начала до индекса конца, не включая конец: срез 1:3 даёт 20 и 30, срез без начала — с первого элемента, срез без конца — до последнего.

Третье число в срезе — шаг. [::-1] — весь список задом наперёд. Срез создаёт новый список, исходный не меняется.

Сортировка

a.sort() сортирует сам список, sorted(a) возвращает новый отсортированный список, а исходный не трогает:

Python
nums = [5, 2, 9, 1]
print(sorted(nums))
print(nums)
nums.sort(reverse=True)
print(nums)
Вывод
[1, 2, 5, 9]
[5, 2, 9, 1]
[9, 5, 2, 1]

reverse=True — по убыванию. Сортировка по длине, по алфавиту без учёта регистра и другие случаи — в справке Как отсортировать список.

Список с клавиатуры

Числа часто вводят в одной строке через пробел. split() разрезает строку на части, map(int, …) превращает каждую часть в число, list(…) собирает результат в список:

Python
nums = list(map(int, input().split()))
print(nums)
print(sum(nums))
Ввод
3 1 4 1 5
Вывод
[3, 1, 4, 1, 5]
14

Подробно о вводе — в справке Как ввести несколько чисел в одной строке.

Список по правилу

Список можно построить одной строкой — это называется генератор списка (list comprehension):

Python
squares = [x * x for x in range(1, 6)]
print(squares)
evens = [x for x in range(10) if x % 2 == 0]
print(evens)
Вывод
[1, 4, 9, 16, 25]
[0, 2, 4, 6, 8]

Читается так: «x * x для каждого x из ряда 1…5» и «x для каждого x из 0…9, если x чётное». То же самое можно сделать обычным циклом с append, но длиннее.

Ловушка: копия списка

Присваивание b = a не копирует список: обе переменные указывают на один и тот же список. Изменение через b видно и через a. Настоящую копию делает a.copy() (или срез a[:]):

Python
a = [1, 2, 3]
b = a
b.append(4)
print(a)
c = a.copy()
c.append(5)
print(a)
print(c)
Вывод
[1, 2, 3, 4]
[1, 2, 3, 4]
[1, 2, 3, 4, 5]
b = a b.append(4) a b 1 2 3 4 один список на два имени c = a.copy() c.append(5) a c 1 2 3 4 1 2 3 4 5 два разных списка
После b = a оба имени указывают на один и тот же список, и append через b меняет и a, а a.copy() создаёт второй, отдельный список.

Список списков

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

Python
bad = [[0] * 3] * 2
bad[0][0] = 1
print(bad)
good = [[0] * 3 for _ in range(2)]
good[0][0] = 1
print(good)
Вывод
[[1, 0, 0], [1, 0, 0]]
[[1, 0, 0], [0, 0, 0]]

[[0] * 3] * 2 повторяет одну и ту же строку дважды, поэтому изменение видно в обеих. Генератор создаёт каждую строку заново. Имя _ ставят вместо переменной, которая не нужна.

Коротко

Проверьте себя

1. Что выведет программа?
Python
a = [5, 10, 15, 20]
print(a[1], a[-1])
2. Как добавить число 7 в конец списка nums?
3. Что выведет программа?
Python
a = [1, 2, 3]
b = a
b.append(4)
print(len(a))
4. Что даёт срез [10, 20, 30, 40][1:3]?