Разгадка управления памятью списков Python
Уровень 0 — Введение:
Списки — неотъемлемая часть экосистемы Python. Для новичков список — это набор типов данных или объектов, заключенных в [ ] и разделенных запятой. Они гетерогенны, изменчивы, упорядочены и индексируемы, что делает их одной из самых OP (мощных) структур данных. В этой статье демонстрируется управление памятью списков с помощью классической игры «Крестики-нолики».
Уровень 1 — Построение крестиков-ноликов:
В этом разделе мы воспроизведем игру в крестики-нолики, используя списки Python. Мы могли бы использовать приведенный ниже синтаксис, чтобы получить общее представление о создании списка.
# empty list ls = [] # list creation with elements ls = [1, 2, 3, "Python", 3.8] print(ls) output: [1, 2, 3, 'Python', 3.8]
Опираясь на приведенный выше синтаксис, мы можем использовать символ «*» для умножения элементов списка и, таким образом, создания доски.
# board creation board = [[“ ”] * 3 ] * 3 print(board) output: [[' ', ' ', ' '], [' ', ' ', ' '], [' ', ' ', ' ']]
Расшифровка внутренних блоков создания доски:
1. [“ ”] → пустой список
2. [“ ”] * 3 → выдаст [“ ”, “ ”, “ ”]
3. [[“ ”] * 3 ] * 3 → даст [[“ ”, “ ”, “ ”], [“ ”, “ ”, “ ”], [“ ”, “ ”, “ ”]]< br /> 4. Следовательно, присваиваем [[“ ”] * 3 ] * 3 переменной board.
Приведенный выше вывод [[“ ”, “ ”, “ ”], [“ ”, “ ”, “ ”], [“ ”, “ ”, “ ”]] можно представить как 3 X 3 крестики-нолики.
Уровень 2 — Выигрыши:
Чтобы получить доступ к элементам, мы могли бы использовать подход board[n-1][m-1], где n = строка и m = столбец. Например,
1. Чтобы получить первый элемент, мы могли бы передать board[0][0] (индекс начинается с 0),
2. Второй элемент в первой строке, board[0][1]
3. Второй элемент в первом столбце, board[1][0]
4. Последний элемент → board[2][ 2]
5. Если мы попытаемся получить элементы вне списка, доски[2][3] или доски[3][2], мы получим IndexError: list индекс вне допустимого диапазона.
Теперь, когда мы привыкли к созданию списка, дизайну доски для игры в крестики-нолики и доступу к элементам с доски, давайте перейдем к МОМЕНТУ, КОТОРОГО МЫ ДОЛЖНЫ ЖДАТЬ!
Первым оптимальным ходом в игре будет размещение «X» в любом углу доски.
# Assigning the first move(element) to "X" board[0][0] = "X"
Ожидания:
Реальность:
print(board)
Поздравляем с победой в крестики-нолики одним ходом. Был ли это счастливый случай? Давайте узнаем в следующем разделе.
Уровень 3 — расшифровка
Прежде чем мы углубимся в то, что именно произошло, давайте рассмотрим операции в мельчайших деталях. Когда мы просматриваем адреса памяти всех блоков пустой переменной board(используя id()), все элементы указывают на один адрес(представленный в приведенном ниже коде и на изображении ).
# board creation board = [[“ ”] * 3 ] * 3 # memory addresses of board rows id(board[0]) == id(board[1]) == id(board[2]) output: True # memory addresses of random elements id(board[0][0]) == id(board[1][2]) == id(board[2][1]) output: True
Когда мы обновляем board[0][0] = «X», для board[0][0] создается новый id для хранения значения «X». Поскольку все три строки доски (board[0], board[1], board[2]) указывают на одну и ту же ячейку памяти, список [“X”, “ ”, “ ” ] обновляется до соответствующих экземпляров строки. Мы можем проверить это, проверив id(board[0][0]) == id(board[1][0]) == id(board[2][0]), который возвращает Истина.
Поэтому, мой друг, ты можешь выиграть крестики-нолики одним ходом. Ну, можно ли не выиграть партию с первого хода?
Финал:
В последнем разделе позвольте мне продемонстрировать способ избежать таких сценариев при работе со списками.
# board creation using list comprehension board = [[" "]*3 for i in range(3)] print(board) output: [[' ', ' ', ' '], [' ', ' ', ' '], [' ', ' ', ' ']] # first move board[0][0] = "X" print(board) output: [['X', ' ', ' '], [' ', ' ', ' '], [' ', ' ', ' ']] # comparing ids id(board[0][0]) == id(board[1][0]) == id(board[2][0]) output: False
Я надеюсь, что эта статья помогла вам понять внутренности управления памятью в списках Python. Я придумаю больше такого содержания в моих следующих статьях.
Любопытный? Взгляните на управление памятью кортежа.
Использованная литература: