python的二维数组生成问题

背景:

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

相关文章
相关标签/搜索