2012-03-03 162 views
0

我想訪問Python中列表的特定元素。我帶了一些C/Java包,並把這個數據結構想象成一個2D數組。在我看來,下面的操作應該隻影響第一個列表的第一項,在Java中的loc1[0][0]會說。實際上,每個子列表的第一項都會受到影響,即loc1[0][0],loc1[1][0]loc1[2][0]。任何想法,爲什麼?Python列表 - 訪問單個元素

def move(loc, dir, nrows, ncols): 
    loc1 = [[0.0] * ncols] * nrows 

    for col in range(1): 
     for row in range(1): 
      loc1[row][col] += 100.0 * loc[row][col] 

    return loc1 
nrows = 4 
ncols = 3 
p = [[1.0/(ncols * nrows)] * ncols] * nrows #uniform prior 

print p 
p = move(p, [0, 1], nrows, ncols) 
print p 
+5

http://docs.python.org/faq/programming.html#how-do-i-create-a-multidimensional-list – 2012-03-03 20:12:58

+0

我們可能有幾十個這個問題的有效重複,但我不知道如何有效地搜索他們:( – 2012-03-03 21:03:43

回答

4

我以前曾經遇到過這種情況,這很令人沮喪。

你的問題是這行代碼,這不是做你認爲它是:

loc1 = [[0.0] * ncols] * nrows 

[0.0] * ncols創建通過引用傳遞到形成你的2D列表中的一個列表。

試試這個:

loc1 = [[0.0 for y in range(ncols)] for x in range(nrows)] 
+0

我有時想知道誰設計了這個,謝謝,它的工作,將在7分鐘內接受。 – mbatchkarov 2012-03-03 20:09:27

+0

看到我的更新的答案,我不是很清楚它 – Blender 2012-03-03 20:11:41

+3

@reseter:任何事情和一切在Python中是「通過引用傳遞的」[沒有變量只有名字](http://python.net/~goodger/projects/pycon/2007/idiomatic/handout.html#other-languages-have-variables)。想象一下,'[x] * n'會複製'x'項目'n'次。您如何定義任意對象的複製操作?它是淺的還是深的複製?您是否僅將操作限制爲「pickleable」對象? – jfs 2012-03-03 20:39:47

3

[x]*n產生包含完全相同的x元素n時間的列表。

L = [0.0] * ncols作品,因爲0.0是float和彩車是不可改變的Python因此L[0] += 1.1不改變0.0,但在它的地方放置1.1

因爲列表是可變的,所以當您更改L = [[0]*ncol]*nrow中的任何行時,由於它們是相同的對象,所以它們全部都會更改。

要解決它,你可以:

L = [[0.0]*ncols for _ in xrange(nrows)] 

它創建了一個新的名單每一行,所以你可以獨立改變它們。

或者:

from itertools import repeat 

L = [[0.0]*ncols for _ in repeat(None, nrows)] 

無論是給你更具可讀性。