Python-Динамический Вложенный Список

поэтому я пытаюсь создать вложенный список в 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 ответов


когда вы [row]*height вы получаете один и тот же объект списка в каждой строке. The 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]

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

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