Проблема здесь:
array_ab = [['?'] * 4] * 3
Проблема вызвана тем, что python решает передать списки вокруг объекта refe Renče. Поскольку список является изменяемым объектом.
Но поскольку списки могут быть довольно большими, а не перемещать весь список вокруг памяти, Python решает просто использовать ссылку («указатель» в терминах C). Если вы назначаете одну другую переменную, вы присваиваете ей только ссылку. Это означает, что вы можете иметь две переменные, указывающие на тот же список в памяти:
>>> a = [1]
>>> b = a
>>> a[0] = 2
>>> print b
[2]
Таким образом, в первой строке кода у вас есть ['?'] * 4
.
Теперь ['?']
является указателем на значение ?
в памяти, и когда вы умножаете его, вы получите 4
указатели на то же место в памяти.
НО когда вы изменяете один из значений, то Python знает, что указатель необходимо изменить, чтобы точки на новое значение:
>>> a = 4 * ['?']
>>> a
['?', '?', '?', '?']]
Вы можете проверить идентификатор элемента в списке:
>>> [id(v) for v in a]
[33302480, 33302480, 33302480, 33302480]
>>> a[0] = 1
>>> a
[1, '?', '?', '?']
Проблема возникает, когда вы умножаете этот список - вы получаете четыре копии указателя списка. Теперь, когда вы меняете одно из значений в одном списке, все четыре меняются вместе.
Предложенный подход заключается в создании списка нужной длины, а затем заполнить в каждом элементе с вновь созданным списком:
>>> A = [None] * 3
>>> for i in range(3):
... A[i] = [None] * 4
...
>>> A
[[None, None, None, None], [None, None, None, None], [None, None, None, None]]
>>>
Это создает список, содержащий 3 различных списки длины 4.
Или Вы можете использовать список понимание:
w, h = 4, 3
A = [[None] * w for i in range(h)]
[[None, None, None, None], [None, None, None, None], [None, None, None, None]]
Edit 2
Основываясь на заголовке, вы не можете выделить точную память для списка в расширенном. Список Python использует какой-то алгоритм, чтобы распределить размер списка для будущего дополнительного роста.
from the source code:
/* This over-allocates proportional to the list size, making room
* for additional growth. The over-allocation is mild, but is
* enough to give linear-time amortized behavior over a long
* sequence of appends() in the presence of a poorly-performing
* system realloc().
* The growth pattern is: 0, 4, 8, 16, 25, 35, 46, 58, 72, 88, ...
*/
Возможно, вы захотите проверить 'numpy'. Это модуль, который много разбирается с массивами. – IanAuld
Это не * лечить * каждую строку как один и тот же объект, каждая строка * есть * тот же объект; умножение только что создало много ссылок на этот объект. Обычно вам не нужно заранее выделять список в Python, они растут по мере добавления к ним элементов. Таким образом, ваш подход к основной проблеме может быть не идеальным - что именно вы планируете делать? –
Тим, спасибо за разъяснение! Я пишу текстовое приключение и хотел создать небольшую «миникарту» сетку, которая начинает пустую, но заполняется, когда вы двигаетесь, меняя «?» до '1'. – JohannesKepler