笔者最近在作一个数据统计程序时,须要用到二维数组。为了一行搞定生成同值二维数组,结果遇到了一些小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最少的库,最高效率,最少代码 去完成是最酷的。至少新手看起来 通俗易懂高大上。