Python - динамический вложенный список - PullRequest
6 голосов
/ 27 августа 2010

Итак, я пытаюсь сгенерировать вложенный список в Python на основе ширины и высоты.Это то, что у меня пока есть:

    width = 4
    height = 5
    row = [None]*width
    map = [row]*height

Теперь это, очевидно, не совсем верно.При печати это выглядит хорошо:

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

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

map[2][3] = 'foo'

Я получаю:

[[None, None, None, 'foo'],
 [None, None, None, 'foo'],
 [None, None, None, 'foo'],
 [None, None, None, 'foo'],
 [None, None, None, 'foo']]

Понятно, что этопроисходит потому, что каждый подсписок на самом деле просто ссылается на один и тот же объект, строку, поэтому, изменяя один, изменяет их все.Так что это самое близкое, что у меня есть!

Как я могу динамически генерировать вложенный список?Спасибо!

Ответы [ 2 ]

11 голосов
/ 27 августа 2010

Когда вы делаете [row]*height, вы получаете один и тот же объект списка в каждой строке. Ссылка на массив row повторяется в каждой строке, что означает, что каждая строка фактически указывает на один и тот же объект списка. Следовательно, изменение одной строки фактически изменяет все строки.

Посмотрите, что происходит, когда вы печатаете id() для каждой строки. Они все одинаковые!

>>> grid = [[None] * width] * height
>>> [id(row) for row in grid]
[148014860, 148014860, 148014860, 148014860, 148014860]

Вы можете заставить python генерировать отдельные, но идентичные списки для каждой строки, используя понимание списка. Когда вы используете [rowexpr for i in xrange(height)], тогда rowexpr будет оцениваться один раз в строке. Хитрость заключается в том, чтобы использовать выражение, которое будет приводить к уникальному списку при каждой его оценке.

Это будет иметь больше смысла, если вы увидите это в действии:

>>> grid = [[None] * width for i in xrange(height)]
>>> grid[2][3] = 'foo'
>>> grid
[[None, None, None, None],
 [None, None, None, None],
 [None, None, None, 'foo'],
 [None, None, None, None],
 [None, None, None, None]]

Каждый раз, когда [None] * width оценивается, он генерирует новый список.

>>> [id(row) for row in grid]
[148016172, 148015212, 148016236, 148016108, 148016332]
0 голосов
/ 27 августа 2010

Я использую что-то вроде этого:

w = 5
h = 5

map = []

for i in range(h):
 row = []
 for j in range(w):
  row.append(None)
 map.append(row)

print map

map[2][3] = 'foo'

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