Списки
Храним много чисел в одной переменной. Индексы, append, sum и max, соседние элементы и генераторы списков. Без этой темы не решить №17, 26 и 27.
- 1Создание и индексы
- 2sum, min, max и другие
- 3Перебор и соседи
- 4Генераторы списков
- 5Изменение списка
- 6Сломай код
- 7Где пригодится на ЕГЭ
Создание и индексы
Список это много значений в одной переменной. Пишется в квадратных скобках через запятую:
a = [12, 7, 30, 5] print(a) print(a[0]) # первый элемент print(a[-1]) # последний print(len(a)) # сколько элементов
Индексы такие же, как у строк: с нуля, отрицательные считают с конца. Срезы тоже работают: a[:2] это первые два элемента.
Обычно список не пишут руками, а наполняют в цикле. Начинают с пустого [] и добавляют элементы через append:
a = [] for n in range(1, 31): if 30 % n == 0: a.append(n) # добавили делитель в конец списка print(a) print('Делителей:', len(a))
Так удобнее, чем счётчик из темы 3: сразу видно не только сколько делителей, но и какие.
sum, min, max и другие
Для списков есть готовые функции, и с ними половина задач решается в одну строку:
| Запись | Что даёт |
|---|---|
sum(a) | сумма |
min(a), max(a) | наименьший и наибольший |
len(a) | сколько элементов |
a.count(5) | сколько раз встречается 5 |
5 in a | есть ли 5 в списке |
a.index(5) | индекс первого вхождения 5 |
a = [12, 7, 30, 5, 18, 41, 3, 26] print(sum(a), min(a), max(a)) print('Среднее:', sum(a) / len(a)) print(41 in a, a.index(41))
Сколько чисел в списке [12, 7, 30, 5, 18, 41, 3, 26] больше среднего арифметического всех чисел?
Перебор и соседи
Перебирать список можно двумя способами, как строку.
По значениям, когда нужен только сам элемент:
a = [12, 7, 30, 5, 18] for x in a: if x % 2 == 0: print(x)
По индексам, когда важно место элемента или его соседи:
a = [12, 7, 30, 5, 18, 41, 3, 26] k = 0 for i in range(len(a) - 1): # до предпоследнего: у последнего нет соседа справа if a[i] > a[i + 1]: k += 1 print(a[i], a[i + 1]) print('Пар, где первое больше второго:', k)
Это ровно то, о чём №17: «пара это два соседних элемента последовательности». Разница только в том, что на экзамене числа будут в файле, а условие длиннее.
Для списка [12, 7, 30, 5, 18, 41, 3, 26] найди наибольшую сумму двух соседних элементов.
Генераторы списков
Цикл с append встречается так часто, что для него есть короткая запись:
# длинно a = [] for n in range(1, 31): if 30 % n == 0: a.append(n) print(a) # коротко, то же самое b = [n for n in range(1, 31) if 30 % n == 0] print(b)
Читается почти как по-русски: «n для каждого n от 1 до 30, если 30 делится на n». Перед for можно написать выражение, тогда в список попадёт не само n, а то, что из него получилось:
print([n * n for n in range(1, 6)]) # квадраты print([int(c) for c in '2026']) # цифры числа print(sum([int(c) for c in '2026'])) # сумма цифр в одну строку
Генератор хорош для простого «отбери и посчитай». Если внутри больше одного условия или нужны промежуточные переменные, пиши обычный цикл: его проще проверить и найти ошибку.
Чему равна сумма квадратов всех нечётных чисел от 1 до 99?
Сколько чисел от 1 до 1000 делятся на 3 и при этом являются палиндромами?
Изменение списка
В отличие от строки, список можно менять по элементу:
a = [12, 7, 30] a[1] = 100 print(a)
Обмен местами
Поменять два элемента местами хочется так: a[0] = a[2], потом a[2] = a[0]. Но это не работает:
a = [1, 2, 3] a[0] = a[2] # теперь a[0] = 3 a[2] = a[0] # a[2] = 3, исходная 1 уже потеряна print(a)
Команды выполняются по очереди, и после первой строки старого значения уже нет. В Python есть короткая запись, которая меняет местами сразу:
a = [1, 2, 3] a[0], a[2] = a[2], a[0] print(a)
Так же меняют местами две переменные: x, y = y, x.
Сортировка
a.sort() сортирует сам список, sorted(a) возвращает новый отсортированный, а старый не трогает. По убыванию: reverse=True.
a = [12, 7, 30, 5] print(sorted(a)) print(sorted(a, reverse=True)) print(a) # исходный не изменился
Подробно про сортировку, в том числе по хитрому правилу, будет в теме 11.
Сломай код
IndexError: сосед за краем
a = [1, 2, 3] for i in range(len(a)): print(a[i] + a[i + 1])
list index out of range. На последнем элементе a[i + 1] выходит за конец. Для соседей нужен range(len(a) - 1).
Тихая ошибка: a = a.append(…)
a = [1, 2] a = a.append(3) print(a)
Вывелось None. append меняет список на месте и ничего не возвращает. Присвоив результат обратно в a, мы потеряли список. Пиши просто a.append(3). С sort то же самое: a = a.sort() даст None.
Тихая ошибка: копия, которая не копия
a = [1, 2, 3] b = a # кажется, что это копия b.append(4) print(a)
Изменили b, а поменялся и a. b = a не копирует список, а даёт ему второе имя. Настоящая копия: b = a.copy() или b = a[:].
Где пригодится на ЕГЭ
| Номер | Что из темы |
|---|---|
| №17 | соседние элементы a[i] и a[i + 1], max, счётчик пар |
| №25 | список делителей через генератор |
| №26 | сортировка, перебор отсортированного списка |
| №27 | списки точек, суммы и минимумы |
Как выглядит №25 со списком делителей. Найдём все делители числа 120, кроме 1 и самого числа, и их сумму:
n = 120 d = [x for x in range(2, n) if n % x == 0] print(d) print(len(d), sum(d))
В №25 обычно спрашивают про числа в большом диапазоне, и перебор до n будет медленным. Как ускорить, разберём в теме 7, когда появятся функции.
Код в блоках можно менять и запускать прямо в браузере.