Перечисление списка списков

Я новичок в программировании, и у меня есть эта основная проблема, которую я не могу исправить. Я упростил его как можно больше. В этой упрощенной версии я повторяю пустой список. Я просто хочу сохранить индексы в «симметричной матрице»:

n = 2 B = [[None] * n] * n print B, "\n" for i in range(n): for j in range(n): B[i][j] = [i, j] print B 

Первоначально список выглядит следующим образом:

 [[None, None], [None, None]] 

После циклического желоба я ожидаю, что распечатка будет следующей:

 [[[0, 0], None], [None, None]] [[[0, 0], [0, 1]], [None, None]] [[[1, 0], [0, 1]], [[1, 0], None]] [[[1, 0], [1, 1]], [[1, 0], [1, 1]]] 

Вместо этого я получаю следующее:

 [[[0, 0], None], [[0, 0], None]] [[[0, 0], [0, 1]], [[0, 0], [0, 1]]] [[[1, 0], [0, 1]], [[1, 0], [0, 1]]] [[[1, 0], [1, 1]], [[1, 0], [1, 1]]] 

Что мне не хватает? Спасибо, что помогли …

То, что вам нужно, а не текущий способ, которым вы определяете B – это «свежие» экземпляры подсписок:

 B = [[None] * n for _ in range(n)] 

который эквивалентен, но короче и (для Pythonista) более читабельным, чем:

 B = [] for _ in range(n): B.append([None] * n) 

Это связано с тем, что списки в Python не являются значениями, а объектами; т.е. они не копируются по умолчанию. Например:

 >>> a = [] >>> b = [a, a] # list of 2 items, both pointing to the same list instance >>> b[0].append(1) # b[0] refers to the same list instance also referenced by a >>> print b [[1], [1]] 

в то время как:

 >>> b = [[], []] # list of 2 distinct sublists >>> b[0].append(1) >>> print b [[1], []] 

Если вы применяете эти знания для

 B = [[None] * n] * n 

вы увидите, что в конструкции возникла ошибка: вы создаете список, содержащий другой список n значений None ; вы затем «увеличиваете» список, чтобы содержать n таких списков; однако тот же экземпляр списка будет использоваться так же, как в приведенном выше, более тривиальные примеры.

PS более точно, все в Python – это объект, а не значение, за исключением случаев, когда объект неизменен, например int s и float s и str s и т. Д., Это как если бы они были значениями и всегда копируются – это потому, что если объект неизменен, вы можете также притворяться, что новая ссылка на него является его новой копией, потому что она выглядит одинаково и не может быть изменена.

Ваша инициализация создает две ссылки на один и тот же список:

 n=2 B=[[None]*n]*n for x in B: print id(x) 

Вывод:

 4534759576 4534759576 

Ключом к пониманию того, что здесь происходит, является понимание того, что вы создаете списки с общими ссылками, когда используете метод [[None]*n]*n . Посмотрите на эту визуализацию того, что делает ваш код, это должно сделать вещи более ясными. Это сообщение в блоге также объясняет, как имена и ценности работают в Python.

Вот как вы могли бы сделать, чего хотите:

  n=2 B = [[None for i in range(n)] for i in range(n)] print B, "\n" for i in range(n): for j in range(n): B[i][j] = [i, j] print B