Изменение значения в нескольких позициях в списке списка при попытке изменить в одном месте - PullRequest
3 голосов
/ 23 ноября 2011

Следующий код в python:

matrix = [[0]*3]*2
matrix[0][1] = 1

кажется, что значение изменяется во всех matrix[][1] -ых позициях, матрица становится [[0,1,0],[0,1,0]] вместо [[0,1,0],[0,0,0]].

Это проблема с инициализацией переменной или поведение по умолчанию в python.

Также Как изменить только одно значение за раз.

Ответы [ 2 ]

6 голосов
/ 23 ноября 2011

Есть некоторые тонкости в том, как оператор умножения * работает со списками в python.

В более общем плане, существуют различия в его эффектах при применении к неизменным объектам, таким как целые числа или строки, и к тому, как они применяются при применении к mutable объектам, таким как списки и словари. 1008 *

Это может прояснить проблему:

>>> l = [0] * 3  #a list of immutable integers
>>> l
[0, 0, 0]
>>> l[0] = 1
>>> l
[1, 0, 0]
>>> l = [[0]] * 3  #a list of mutable lists
>>> l
[[0], [0], [0]]
>>> l[0][0] = 1
>>> l
[[1], [1], [1]]

РЕДАКТИРОВАТЬ (спасибо @lazyr в комментариях) В обоих случаях оператор * создает список объектов с одинаковой идентичностью (адресом памяти), поэтому каждое число (и каждый список) в массиве - это на самом деле один и тот же объект, однако неизменяемые типы нельзя изменять, а только заменять, поэтому при попытке назначить новое значение целочисленному массиву вы фактически замените весь объект, хотя это не так. случай со списками. На основании предыдущего примера (имейте в виду, что функция id возвращает адрес памяти объекта):

>>> m = [1] * 3
>>> id(m[0])
39356344
>>> id(m[1])
39356344
>>> m[1] = 2
>>> id(m[1])
39356320  # new memory addres = different object!
>>> m = [[1]] * 3
>>> id(m[0])
40275408
>>> id(m[1])
40275408
>>> m[1][0] = 2
>>> id(m[1])
40275408  # same memory address = still the same object!

Итак, в вашем случае возможный обходной путь - инициализация матрицы следующим образом:

>>> matrix = [[0 for i in range(3)] for j in range(2)]
>>> matrix
[[0, 0, 0], [0, 0, 0]]
>>> matrix[0][2] = 1
>>> matrix
[[0, 1, 0], [0, 0, 0]]

Альтернативным, более радикальным способом было бы вообще переключиться на numpy , который быстрее и продуман с нуля для чрезвычайно быстрой манипуляции с матричными и многомерными векторами, но его также сложнее использовать.

НТН!

3 голосов
/ 23 ноября 2011

Попробуйте:

matrix = [[0]*3 for j in xrange(2)]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...