Примеры реализации вложенных списков в реальных примерах. Наборы коодинат, сложный инвертарь внутри игры или товары с различными характеристиками – всё это примеры реализации вложенных списков.
Мы подошли к полноценной работе с различными данными в программировании. Как правило, данные группируются между собой, и с этими "группами" данных программисты, как правило, и работают. Одну из таких "групп" вы уже знаете – это списки.
В программировании данные часто имеют более сложную структуру, чем простой список чисел или строк. Например, представьте таблицу, где каждая строка содержит данные о человеке: имя, возраст, и город проживания. Или шахматную доску, представленную как матрицу, где каждый элемент — это клетка доски. Такие данные лучше всего описываются с помощью вложенных списков — списков, которые содержат другие списки.
Представим таблицу, в которой два столбца: первый содержит название товара, а второй — его цену. Это полезно для описания, например, списка товаров в магазине.
Чтобы выбрать отдельную строку мы пройдемся по номерам (1, 2, 3), а значение в ячеке – по буквам столбцов (А, Б).
Выбор в списках работает по похожему принципу.
Таблицу можно представить как коллекцию строк(табличных). Каждая строка — это пара значений: название и цена. Вместо работы с таблицей как с абстрактной концепцией, в программировании удобно разбить её на части: вся таблица становится списком строк, а каждая строка — это вложенный список.
В Python это реализуется через вложенные списки. Внешний список выполняет роль контейнера для всех строк таблицы, а каждый вложенный список хранит данные одной строки.
Внешний список — это "каркас" таблицы.
Вложенные списки — это строки таблицы, каждая из которых состоит из двух элементов.
Теперь разберем, как обращаться к данным в такой структуре. Для этого используются индексы. Индексация начинается с нуля.
Чтобы получить, например, строку, в которой содержита информация о банане, нужно обратиться по индексу 1 списка products: products[1]
Чтобы получить конкретный элемент строки, используется второй индекс. Например, если вас интересует цена из первой строки (по индексу), нужно обратиться к первому элементу вложенного списка: products[1][1]
Таким образом можно "углубляться" внутрь структуры данных.
Чтобы добавить новую строку, достаточно использовать метод append. А чтобы добавить значение во вложенный список, нужно будет добавлять в него по индесу основного списка.
В Python вложенные списки позволяют представлять многомерные структуры данных, такие как таблицы или матрицы. Для эффективного извлечения и отображения данных из таких структур используются вложенные циклы.
Чтобы вывести все элементы таблицы построчно, можно использовать вложенные циклы for. При этом, сначала нужно делать "проход" по внешнему списку, а потом еще и по внутренним.
Логичное представление данных. Каждая строка соответствует одной логической сущности (продукту), а каждый столбец — одному атрибуту (название и цена). Это делает данные легко читаемыми и структурированными.
Универсальность доступа. Используя индексацию, можно извлекать как строки целиком, так и конкретные элементы внутри строк. Это упрощает обработку данных.
Расширяемость. Новые строки легко добавляются к таблице, а доступ к любым данным остается предельно простым.
Создайте файл entry_list.py
Вы организатор мероприятия, на котором участвуют гости. У вас есть список участников, где для каждого указаны имя, фамилия и статус участия (например, "зарегистрирован", "на месте", "отсутствует"). Ваша задача — создать структуру данных для управления участниками и выполнить несколько операций с этим списком.
Создайте вложенный список со следующей структурой: <имя>, <фамилия>, <статус>
Где "Статус" может быть "на месте", "отсуствтует" или "зарегистрирован".
Напишите несколько функций для работы с этиим списком:
Функция show_all: выводит список всех участников, пример:
Иван Иванов: зарегистрирован
Мария Смирнова: на месте
Александр Петров: на месте
Екатерина Соколова: зарегистрирован
Функция at_point: выводит список только тех участников, чей статус "На месте"
Участники на месте:
Мария Смирнова
Александр Петров
Функция change_point: изменяет статус участника.
Функция add_member: при вызове предлагает ввести имя и фамилию через пробел, а после запятой - статус участника. Вносит данные в основной список, если такого участника нет (совпадение по имени + фамилии). Если такой участник есть - меняет его статус на тот, который был указан. Можете вызывать функцию change_point.
Функция delete_member: удаляет участника. Пользователь указывает имя и фамилию через пробел.
Сделайте вызов всех функций поочередно, либо реализуйте небольшой консольный интерфейс.
Когда мы работаем с вложенными списками в Python, часто возникает необходимость создать их автоматически, например, заполнить таблицу числами, инициализировать матрицу нулями или задать определённый шаблон данных. Такой подход называется генерацией вложенных массивов, и для этого Python предоставляет мощные инструменты, такие как вложенные списковые включения.
Мы их уже рассматривали в главе про цикл for, но теперь рассмотрим их в контексте вложенных списков.
– Так, стоп. Я уже который раз вижу слово "матрицы", однако все это время мы работаем просто со вложенными списками. Есть какое-то отличие?
– Хороший вопрос! Вообще матрицы в python реализуются как вложенные списки. Никакой магии: просто список, в котором хранятся другие списки. А матрицами их называют, потому что термин пришёл из математики.
– Эм.. а может отличия есть какие-то?
– Ну вообще, за матрицами закреплено то, что у матриц есть определенный размер, N строк на M столбцов. Поэтому, их удобно организовывать в таблицу. При этом считается, что длина вложенного списка должна быть строго M, иначе уже матрицей назвать это нельзя. А еще у них есть "мерность". Например, одномерная матрица представляет собой 1 строку на M столбцов, но нам проще сказать, что это список. NxM – это двухмерная матрица, NxMxZ – трехмерная и так далее.
– Так, вроде бы понятно. А что на счет массивов? Это то же самое, что и матрица?
– Почти! В Python массивы предоставляются библиотекой numpy, и они куда мощнее, чем просто вложенные списки. С ними можно выполнять крутые математические операции, например, умножение матриц или вычисление определителей. Но для базовой концепции нам достаточно вложенных списков.
– То есть матрица – это просто идея, которую можно реализовать списками или массивами?
– Все именно так! Можно считать, что "матрица" – это математическая концепция, а вложенные списки или массивы – это инструменты для реализации её в программах.
Допустим, нужно создать таблицу размером 3x3, заполненную нулями:
matrix = [[0 for _ in range(3)] for _ in range(3)]
Внешнее включение for _ in range(3) — отвечает за строки таблицы.
Внутреннее включение for _ in range(3) — создаёт элементы строки (список из трёх нулей).
[0 for _ in range(3)] создаёт строку [0, 0, 0], а внешний цикл повторяет это трижды, формируя таблицу.
Результат:
[
[0, 0, 0],
[0, 0, 0],
[0, 0, 0]
]
Иногда нужно работать с более сложными структурами, например, трёхмерными массивами (3D-матрицы). Допустим, мы хотим создать куб размером 3x3x3, где каждый элемент равен сумме его координат:
cube = [[[x + y + z for z in range(3)] for y in range(3)] for x in range(3)]
Внешний цикл for x in range(3) создаёт "слои" куба.
Средний цикл for y in range(3) создаёт строки внутри слоя.
Внутренний цикл for z in range(3) формирует элементы строки.
Формула x + y + z вычисляет значение каждого элемента.
Результат:
[
[[0, 1, 2], [1, 2, 3], [2, 3, 4]],
[[1, 2, 3], [2, 3, 4], [3, 4, 5]],
[[2, 3, 4], [3, 4, 5], [4, 5, 6]]
]
Инициализация данных. Например, создание пустой матрицы или заполненной шаблоном.
Симуляции и игры. Генерация игровых полей, шахматных досок, лабиринтов и т.п.
Математические задачи. Построение таблиц значений, матриц, трёхмерных объектов.
Избегайте общих ссылок. При генерации списков важно, чтобы каждая строка была отдельным объектом. Используйте вложенные включения, а не умножение списка:
wrong_matrix = [[0] * 3] * 3 # Ошибка! Все строки будут ссылаться на один объект.
correct_matrix = [[0 for _ in range(3)] for _ in range(3)] # Правильно.
Читаемость кода. Генерация массивов с помощью вложенных списковых включений — мощный инструмент, но слишком сложные конструкции могут быть трудны для понимания. В таких случаях лучше использовать обычные циклы.
Создайте файл snowflake.py
В этой задачке нужно написать программу, которая спрашивает у пользователя размер снежинки (N), а в ответ выводит рисунок снежинки NxN.
Условие:
Программа запрашивает у пользователя целое число n (размер матрицы):
Если n нечётное, используется введённое значение.
Если n чётное, программа автоматически увеличивает его на 1 и выводит сообщение: “Размер был изменён на n+1 , чтобы сделать его нечётным.”
Создайте квадратный массив размером n \times n , заполненный символом точки (•).
Заполните массив символами * по следующим правилам:
Символ * располагается в средней строке.
Символ * располагается в среднем столбце.
Символ * располагается на главной диагонали (идущей слева направо сверху вниз).
Символ * располагается на побочной диагонали (идущей справа налево сверху вниз).
Выведите полученный массив на экран. Для удобства чтения элементы строки должны быть разделены пробелами.
(дополнительно) Для красоты, сделайте так, чтобы все точки были белого цвета (или черным, чтобы не было видно в консоли системы), а звездочки - голубого цвета.
Пример работы программы:
Введите нечётное число: 4
Размер был изменён на 5, чтобы сделать его нечётным.
* • * • *
• * * * •
* * * * *
• * * * •
* • * • *
Давайте быстро поговорим про такую штуку, как кортежи.
Если списки — это рабочие лошадки в Python, то кортежи — это их более изящные и стабильные родственники. Они умеют почти всё то же, что и списки, но с одним важным отличием: кортежи неизменяемы. Это значит, что после создания их нельзя редактировать. И хоть это может сначала показаться ограничением, неизменяемость часто оказывается мощным инструментом.
Представьте, что у вас есть набор данных, который не должен меняться. Например, координаты на карте (широта, долгота), дни недели, цвета радуги или что-то ещё, что логично оставить таким, как есть. Вот тут кортежи становятся незаменимыми.
Кортежи безопасны. За счет того, что их нельзя изменять, можно не ждать, что какие-то данные потеряются по ходу кода или будут изменены.
Кортежи быстрее списков. Так сходу это не заметно, но в больших данных – это принципиальная разница.
Не считая изменений – имеют все те же функции, что и списки.
Вложенные списки — это инструмент для работы с динамическими, изменяемыми данными. Они полезны, когда данные структурированы в виде таблиц, матриц или более сложных форм.
Кортежи обеспечивают надёжность и неизменяемость, их следует использовать для фиксированных и постоянных данных.
Оба инструмента дополняют друг друга, и выбор между ними зависит от характера данных и задачи, которую вы решаете.