Разница между [[0] * m] * n и [[0 для i в диапазоне (0, m)] для j в диапазоне (0, n)] - PullRequest
0 голосов
/ 26 мая 2020

Я пытаюсь создать список размера n, каждый элемент которого также является списком размера m. После создания списка я выполняю следующую операцию.

matrix=[[0]*m]*n 
# matrix = [[0 for i in range(0,m)] for j in range(0,n)]
m=2
n=3
ind=[[0,1][1,1]]
for r,c in ind:
   for i in range(m):
      matrix[r][i]+=1
   for j in range(n):
      matrix[j][c]+=1
print(matrix)

Вышеупомянутая операция ищет значение строки и столбца в списке «ind» и увеличивает значение на одну из соответствующих строк и столбцов. .

Проблема в том, что когда я использую инициализацию матрицы как [[0] * m] * n, тогда результат будет другим, и когда я использую matrix = [[0 for i in range (0, m )] для j в диапазоне (0, n)] результат будет правильным. В первом случае значения меняются для всех строк, столбцов, которых быть не должно.

Я попытался указать тип отдельных элементов списка матриц, а также получить тип элемента элемента матрицы с помощью print (type (matrix [0])) и print (type (matrix [0] [0]))

Оба имеют одинаковый тип. Есть идеи, почему результат матрицы отличается для двух разных типов инициализации?

Спасибо за помощь.

1 Ответ

0 голосов
/ 26 мая 2020

Когда вы делаете:

[0]*m

, вы создаете список, который мы назовем l1. Итак, следующий шаг:

[[0]*m]*n 

Эквивалентен:

[l1]*n

Это не копирует l1 несколько раз, а скорее делает несколько ссылки на него. Проблема с классическим c глубоким копированием и мелким копированием.

Вы можете подтвердить это, проверив, что следующее выражение True

matrix[0] is matrix[1]

Используя понимание списка, каждая строка другой список, поэтому у вас не будет этой проблемы

matrix=[[0]*m for _ in range(n)] 

Вы можете задаться вопросом, почему эта ссылка является проблемой для списков, но вы можете сделать [0]*m, не беспокоясь о том, что все 0 фактически ссылаются на одно и то же значение.

Разница здесь в типе, списки будут копироваться по ссылке по умолчанию, поскольку длинные списки могут быть дорогостоящими для копирования по значению. ints довольно дешево копировать, поэтому создавать ссылки не имеет большого смысла

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...