переназначение строки / списка в 2D-списке в Python - PullRequest
2 голосов
/ 08 декабря 2011

Я пытался создать 2-мерный список в Python, который был размером x + 1, y + 1 и имел некоторые начальные значения. Эти начальные значения состоят в том, что первая строка содержит числа от 0 до «x», а первый столбец содержит числа от 0 до «y» (оба включительно)

Допустим, х и у были 3 и 4.

Итак, я пошел: listName = [диапазон (0, х + 1)] * (у + 1);

Это дает мне двухмерный список, который состоит из 5 строк, и каждая строка представляет собой список с номерами от 0 до 3, дающий 4 индекса в каждой строке (4 столбца):

[[0, 1, 2, 3], 
 [0, 1, 2, 3], 
 [0, 1, 2, 3], 
 [0, 1, 2, 3], 
 [0, 1, 2, 3]]

Я понимаю, что на данный момент у меня есть двумерный массив, но каждая строка является экземпляром, поэтому, если бы я изменил какое-либо значение в каждой строке, все строки отражали бы это изменение. Чтобы исправить это, я решил установить для каждой строки новый уникальный список:

for row in listName:
    row = range(0, x + 1);

Но я заметил, что это, кажется, не имеет никакого эффекта, мой оригинальный список, Даже если я пошел:

for row in listName:
    row = ["A", "B", "C", "D"];

Печать до и после назначения показывает, что «строка» изменяется, но за пределами цикла я получаю свой исходный список при печати. Несмотря на то, что я нашел другой способ сделать то, что я хочу, я не могу понять, почему это происходит. Есть идеи?

Ответы [ 3 ]

1 голос
/ 08 декабря 2011

Slice-assign для изменения существующего списка, а не просто повторного связывания имени.

row[:] = ...

Кроме того, вы неправильно его конструируете.

listName = [range(0, x + 1) for z in range(y + 1)]
0 голосов
/ 08 декабря 2011

Но я заметил, что это, кажется, не имеет никакого эффекта, мой первоначальный список

, потому что row = range(0, x + 1) не означает "Содержимое вещи, на которую ссылается row, должно бытьзаменено на содержимое списка range(0, x + 1) ";это означает «имя row перестает ссылаться на то, к чему оно относится в настоящее время, и вместо этого ссылается на список range(0, x + 1)».

0 голосов
/ 08 декабря 2011

Когда вы назначаете список имени, вы фактически создаете новый список. Python имеет специальный синтаксис, который позволяет вам сделать это:

row[:] = …

>>> listName = [range(0, x + 1)] * (y + 1);
>>> listName
[[0, 1, 2, 3], [0, 1, 2, 3], [0, 1, 2, 3], [0, 1, 2, 3], [0, 1, 2, 3]]
>>> for row in listName:
...     row[:] = range(0, x+1)
... 
>>> listName
[[0, 1, 2, 3], [0, 1, 2, 3], [0, 1, 2, 3], [0, 1, 2, 3], [0, 1, 2, 3]]
>>> for row in listName:
...     row[:] = range(0, x+6)
... 
>>> listName
[[0, 1, 2, 3, 4, 5, 6, 7, 8], [0, 1, 2, 3, 4, 5, 6, 7, 8], [0, 1, 2, 3, 4, 5, 6, 7, 8], [0, 1, 2, 3, 4, 5, 6, 7, 8], [0, 1, 2, 3, 4, 5, 6, 7, 8]]

Но, исходя из исходного вопроса, вы хотели это сделать?

>>> [range(0, x+1)] + [[i] + [0]*x for i in xrange(1, y+1)]
[[0, 1, 2, 3], [1, 0, 0, 0], [2, 0, 0, 0], [3, 0, 0, 0], [4, 0, 0, 0]]
...