Проблема с списком Python

питон:

m=[[0]*3]*2
for i in range(3):
    m[0][i]=1

print m

Я ожидаю, что этот код должен печатать

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

но он печатает

[[1, 1, 1], [1, 1, 1]] 

Ответ 1

Это по дизайну. Когда вы используете умножение на элементах списка, вы воспроизводите ссылки.

Смотрите раздел "Сочетания создания списка" в Python Programming/Lists wikibook, в котором подробно рассматриваются проблемы со списком ссылок на изменяемые объекты.

Их рекомендуемое обходное решение - это понимание списка:

>>> s = [[0]*3 for i in range(2)]
>>> s
[[0, 0, 0], [0, 0, 0]]
>>> s[0][1] = 1
>>> s
[[0, 1, 0], [0, 0, 0]]

Ответ 2

Это немного дьявольски, но совершенно очевидно, когда вы понимаете, что делаете. когда вы делаете бит [[0]*3]*2, вы сначала создаете список с 3 нулями, затем копируете его, чтобы создать два элемента. Но когда вы делаете эту копию, вы не создаете новые списки с тем же содержимым, а ссылаетесь на один и тот же список несколько раз. Поэтому, когда вы меняете один, все они меняются.

Пример, чтобы выделить его:

In [49]: s = [[]]*2 # Create two empty lists

In [50]: s # See: 
Out[50]: [[], []]

In [51]: s[0].append(2) # Alter the first element (or so we think)

In [52]: s # OH MY, they both changed! (because they're the same list!)
Out[52]: [[2], [2]]