標籤:

python 用list of lists表示矩陣的問題?

題主刷leetCode的時候發現的一個小情況&>_&< 不知道緣由是什麼,請各位知友幫忙看看~~

python 初始化 a list of lists of integer,就用了如下方式(假設是4 x 4的方陣):

n = 4

matrix = [[0]*n]*n

print matrix

[[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]]

然後詭異的是,假如我只想給第二行的中間兩個元素賦值:

matrix[1][1:3] = [1, 2]

結果會是:

print matrix

[[0, 1, 2, 0], [0, 1, 2, 0], [0, 1, 2, 0], [0, 1, 2, 0]]

但是如果用如下方式初始化matrix:

matrix = [[0 for col in range(n)] for row in range(n)]

matrix[1][1:3] = [1, 2]

print matrix

[[0, 0, 0, 0], [0, 1, 2, 0], [0, 0, 0, 0], [0, 0, 0, 0]]

會是我想要的答案。

但是不知道第一種初始化方式錯在哪裡...


matrix = [[0]*n]*n

等價於

fuck = [0]*n
matrix = [fuck]*n

後面你都知道了,matrix的四個數組其實都是fuck,他們都是指向同一個數組實例。你改了一個當然會表現為四個都改了。


贊同樓上,另外要處理矩陣相關的話用 NumPy


#!/usr/bin/python
#encoding=utf-8

# 內容來自python cookbook 第二版 第4.5章節
# 在無須共享引用的條件下創建列表的列表
# 避免隱式的引用共享

multi = [ [0] * 5 ] * 3
print multi
multi[0][0] = "oops"
print multi
# [ [ "oops", 0, 0, 0, 0 ],[ "oops", 0, 0, 0, 0],[ "oops", 0, 0, 0, 0 ] ]

# 等價方式
row = [0] * 5 # row 列表中的5個子項都是引用0
multi = row * 3 # multi 列表中的3個子項都是引用row
# 解釋: 在row創建中, 有無引用被複制完全不重要, 因為被引用的
# 是數字, 而數字不可改變,換句話說,如果對象是不可改變的,則
# 對象和對對象的引用實際沒有區別。
# multi創建中,包含了3個對[row] 內容引用,而其內容則是對一個
# 列表的引用。因此修改時候其他3個引用也改變了,甚至row也改變

# 解決方法:
multilist_method1 = [ [ 0 for col in range(5) ] for row in range(3) ]
multilist_method2 = [ [0] * 5 for row in range(3) ]
multilist_method1[0][0] = "abc"
multilist_method2[0][0] = "edf"
print multilist_method1
print multilist_method2


這個問題,在《Python cookbook》第二版p148頁提到,即隱式的引用共享問題。

解決的方案是使用列表推導。

詳細你可以看看書。(不好意思手機碼字懶得寫太多了,希望能解決你的問題。)


第一種是淺拷貝


a=[[0]*3]*3

等價於

b=[0]*3

a=[b]*3

貼一段代碼

b=[0]*3
a=[b]*3
print a
a[0][0]=5
print b
print a

看看這段代碼的輸出結果

[[0, 0, 0], [0, 0, 0], [0, 0, 0]]

[5, 0, 0]

[[5, 0, 0], [5, 0, 0], [5, 0, 0]]

所以a=[b]*3相當於複製三次變數名b(也就是產生了三個別名/引用吧)然後賦予a,改了a中b的別名,相當於改了所有的b。


刷leetcode用python坑多啊,昨天剛遇到一個python的除法和餘數機制和c不一樣啊


推薦閱讀:

python 能否print到console固定一行?
期權的高頻交易回測平台怎麼編寫?
有沒有什麼軟體能夠在Win10系統下將電腦重複的工作自動實現?
python 函數中傳值,傳的是引用還是複製一份傳給另一個函數,會修改調用函數裡面的值嘛?
Mixin是什麼概念?

TAG:Python |