Коллекции: массивы/списки, индексация, срезы🔗
Зачем нужны коллекции: от переменных к спискам🔗
Хранение набора однородных данных через отдельные переменные быстро становится громоздким. Для рецепта с десятью ингредиентами пришлось бы создать десять контейнеров: ingredient_1, ingredient_2 и так далее. Это загромождает код и усложняет передачу данных.
Метафора кухни помогает увидеть разницу. Вместо разбросанных по столу отдельных пакетов, лучше поставить на полке единый органайзер с пронумерованными ячейками — все ингредиенты собраны в одном месте.
В Python эту роль играет список — упорядоченная коллекция элементов. Создается он с помощью квадратных скобок:
ingredients = ['мука', 'яйца', 'молоко']
print(ingredients)
Список — это единое значение, которое можно присвоить переменной, точно как число или строку. Но в отличие от скалярных типов, он хранит множество элементов в строгом порядке. Это первый шаг от простых переменных к структурам данных.
Диаграмма загружается…
Индексация: нумерация контейнеров с нуля🔗
Когда ингредиенты разложены в органайзере, каждая ячейка получает номер. В программировании нумерация начинается с нуля — это не порядковый номер, а смещение от начала. Индекс 0 означает «от начала ноль шагов», то есть самый первый элемент. Индекс 1 — смещение на одну позицию вправо.
shelf = ['мука', 'сахар', 'яйца', 'молоко']
print(shelf[0]) # мука — начало полки, смещение 0
print(shelf[2]) # яйца — отступили на 2 позиции
Отрицательные индексы работают как счёт с правого края: -1 всегда указывает на последний элемент, -2 — на предпоследний. Это особенно удобно, когда длина списка неизвестна заранее.
print(shelf[-1]) # молоко — последний элемент
print(shelf[-4]) # мука — первый элемент с конца
Так выглядит полное соответствие индексов и значений:
| Индекс |
Значение |
Позиция слева |
Позиция справа |
| 0 |
'мука' |
первая |
четвёртая |
| 1 |
'сахар' |
вторая |
третья |
| 2 |
'яйца' |
третья |
вторая |
| 3 |
'молоко' |
четвёртая |
первая |
| -1 |
'молоко' |
— |
первая |
| -2 |
'яйца' |
— |
вторая |
Попытка взять shelf[4] или shelf[-5] вызовет IndexError — аналог пустой ячейки за пределами полки. Чтобы захватить несколько соседних ингредиентов за раз, используют срезы.
Срезы: выбор диапазона ингредиентов🔗
Индексация достаёт один элемент, а кулинарный процесс часто требует групп: первые три ячейки для теста, последние две для глазури или каждый второй ингредиент. Срезы позволяют взять подряд идущие элементы без перебора по одному.
Синтаксис: shelf[start:stop:step]. start — индекс первой позиции (включительно), stop — граница, где выборка обрывается (элемент с этим номером не попадёт в результат), step — шаг.
ingredients = ["мука", "яйца", "молоко", "сахар", "соль", "разрыхлитель"]
# Элементы с 0 по 2 (три первых ингредиента)
dough_base = ingredients[0:3]
print(dough_base) # ['мука', 'яйца', 'молоко']
Если опустить start, отсчёт начинается с нуля; если пропустить stop — забирается всё до конца:
first_two = ingredients[:2] # ['мука', 'яйца']
last_items = ingredients[4:] # ['соль', 'разрыхлитель']
step позволяет брать элементы через одну позицию или двигаться в обратном направлении:
# Каждый второй ингредиент, начиная с первого
alternating = ingredients[::2]
# ['мука', 'молоко', 'соль']
# Разворот: шаг -1 двигает нас от конца к началу
reverse_order = ingredients[::-1]
# ['разрыхлитель', 'соль', 'сахар', 'молоко', 'яйца', 'мука']
Срез создаёт новый список, оставляя исходный нетронутым. Это удобно для резервного копирования перед экспериментами с рецептурой:
original_recipe = ingredients[:] # Полная копия всего содержимого
Так можно виртуально распределять продукты по этапам готовки, не трогая исходный набор. Чтобы изменить состав хранилища — добавить элементы или перебрать существующие — понадобятся операции модификации списка, которые мы разберём далее.
Операции со списками: наполнение и перебор🔗
Кухонная полка — не музейный экспонат: ингредиенты заканчиваются, и их нужно доложить, или наоборот — убрать испорченное. Списки в Python живут такой же жизнью.
Изменение состава
Метод append() ставит новый контейнер в конец:
shelf = ["мука", "сахар"]
shelf.append("яйца") # Теперь три элемента
Метод pop() работает как щипцы: без аргумента забирает последний элемент, с числом — забирает конкретную позицию и закрывает «дырку» (элементы сдвигаются):
last = shelf.pop() # Забрали "яйца"
first = shelf.pop(0) # Забрали "муку", остался ["сахар"]
Подсчет и проверка
Функция len() считает, сколько контейнеров сейчас на полке. Оператор in проверяет наличие ингредиента без перебора:
print(len(shelf)) # 1
print("сахар" in shelf) # True
Два способа перебора
Чтобы пройтись по всей полке, используем цикл for. Если номера ячеек не нужны, перебираем сразу значения:
for item in shelf:
print(f"Взять: {item}")
А когда нужен индекс — например, для нумерации — комбинируем range() и len():
for i in range(len(shelf)):
print(f"{i+1}. {shelf[i]}")
Собираем покупки
Соберем корзину покупок через консольный ввод. Создадим пустой список, наполним его тремя товарами и выведем первые три пункта. Даже если пользователь ввел больше, срез обрежет лишнее:
cart = []
cart.append(input("Первое: "))
cart.append(input("Второе: "))
cart.append(input("Третье: "))
print("План:", cart[:3])
Здесь [:3] — срез из прошлого раздела — гарантирует, что мы увидим только первые три позиции.