筆者最近在作一個數據統計程序時,須要用到二維數組。爲了一行搞定生成同值二維數組,結果遇到了一些小bug,實驗了下,終於找到了問題並修復。python
如何簡單快速生成 連續10個k的字符串,很簡單數組
'k'*10 #kkkkkkkkkk
那如何快速生成 連續十個True的數組(列表)呢?別再for .... xxx.append()了,不美觀也多了好幾行代碼。一行搞定便可。app
[True]*10 #[True, True, True, True, True, True, True, True, True, True]
那若是生成 2x3的全是0的二維數組呢?spa
按照上面的套路還不簡單?也是一行搞定。(筆者也是這麼想的,結果bug了。嘛,先看下結果吧,確實是想要的)手到擒來嘛。指針
[[0]*3]*2 #[[0, 0, 0], [0, 0, 0]]
其實這樣有bug!其實這樣有bug!其實這樣有bug!code
用新舊兩種方法生成全是0的2x3數組,修改座標(1,1)的值爲9.對象
l1 = [[0]*3]*2 l2 = [ [0,0,0], [0,0,0], ] print('l1原',l1) print('l2原',l2) l1[1][1] = 9 l2[1][1] = 9 print('l1改',l1) print('l2改',l2) #結果: #l1原 [[0, 0, 0], [0, 0, 0]] #l2原 [[0, 0, 0], [0, 0, 0]] #l1改 [[0, 9, 0], [0, 9, 0]] #l2改 [[0, 0, 0], [0, 9, 0]]
土方法正常的改值了。咱們帥氣的方法(僞)出現bug了。你會發現全部第二列的數值都改爲了9。內存
爲何呢?字符串
這是由於python的機制問題。class
在python裏,int float str都是深拷貝的,即'x'*n,'x'的值會被複製成n份;
可是list,dist和其餘class等,都是淺拷貝的,即僅僅把對象的內存地址拷貝了一份,全部拷貝出來的數據都會共用一組數據。即c裏咱們常說的指針。
[[0]*3]*2
裏的[0]*3確實進行了深拷貝,因而就至關於變成了 [[0 ,0 ,0 ] ]*2。而外層拷貝變成了拷貝list,即淺拷貝,也就是不管拷貝多少行都在使用同一行的數據。
改變1行數據就變成了改變全部行數據。
所以,正確的寫法是(固然也是 一行 哦)
l3 = [([0] * 3) for i in range(2)] print('l3原',l3) l3[1][1] = 9 print('l3改',l3) #結果 #l3原 [[0, 0, 0], [0, 0, 0]] #l3改 [[0, 0, 0], [0, 9, 0]]
是否是帥氣而簡單呢?
網上還有其餘引用其餘庫的方法去處理。但筆者認爲,import最少的庫,最高效率,最少代碼 去完成是最酷的。至少新手看起來 通俗易懂高大上。