2010-08-27 170 views
6

所以我想基于宽度和高度在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']] 

显然,这是因为每个子表是真的只是引用相同的对象,行,所以改变它,全部改变它们。所以这是我最接近的!

我该如何动态生成一个嵌套列表?谢谢!

+0

虽然不是完全相同的副本,请参阅:http://stackoverflow.com/questions/1605024/python-using-the-multiply-operator-to -create-copies-of-objects-in-lists – carl 2010-08-27 18:52:05

+2

'map()'是一个内置函数,重写它不是一个好主意。找到另一个名字,如果需要的话,你可以追加'_'。 – 2010-08-27 19:04:34

回答

11

当你做[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

我用的是这样的:

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 
+0

列表理解是__one__正确的方法来做到这一点。 – aaronasterling 2010-08-27 19:02:45

+0

我同意,列表理解更清晰,更具可读性,更多'Pythonic'。我的方式只是一种解决问题的方式,对于仍在从C发展为python的人们(如我)也是可读的。 – lalli 2010-08-27 19:10:52

+0

使用嵌套for循环进行循环不会帮助您或其他任何人从C到Python的转换:它只是阻碍。 – aaronasterling 2010-08-27 21:10:23