2010-08-27 113 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