Python - 动态嵌套列表

7 投票
2 回答
10152 浏览
提问于 2025-04-16 03:24

我正在尝试在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 个回答

1

我用的类似这样的东西:

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
12

当你使用 [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]

撰写回答