900字范文,内容丰富有趣,生活中的好帮手!
900字范文 > python初始化空列表_python list的深拷贝与浅拷贝-以及初始化空白list的方法(1)

python初始化空列表_python list的深拷贝与浅拷贝-以及初始化空白list的方法(1)

时间:2022-01-20 04:26:04

相关推荐

python初始化空列表_python list的深拷贝与浅拷贝-以及初始化空白list的方法(1)

在一次做题的时候遇到了一件令人非常匪夷所思的“bug”:我想要做的事情是,初始化shape确定,但值为“空”的list,并且是一个二维的list,开始我是这么做的:

l1=[[""]*3]*3

printl1

[['', '', ''], ['', '', ''], ['', '', '']]

可以看到这个矩阵的shape,可以理解成一个N*N的矩阵。

把题目也贴出来吧——题目要求很简单,输入一个N*N的矩阵,输出这个矩阵的顺时针旋转90°之后的矩阵。一开始我的代码如下:

classRotate:defrotateMatrix(self, mat, n):#write code here

v=[[""]*3]*3

for i inrange(n):for j inrange(n):

v[i][j]=mat[n-j-1][i]return v

输入的测试数据为:

[[1,2,3],[4,5,6],[7,8,9]]

正确的输出应该为:

[[7,4,1],[8,5,2],[9,6,3]]

而我的运行结果却是:

[[9,6,3],[9,6,3],[9,6,3]]

非常不解,输出的三个子数组居然是一样的结果

后来对原来的代码略加修改,把“空”list的初始化定义为:v=[[0 for i in range(n)]for j in range(n)],即:

classRotate:defrotateMatrix(self, mat, n):#write code here

v=[[0 for i in range(n)] for j inrange(n)]for i inrange(n):for j inrange(n):

v[i][j]=mat[n-j-1][i]return v

此时终于输出了正确的结果[[9,6,3],[9,6,3],[9,6,3]],代码测试通过。

这里对比一下这两种初始化方法:

至少在输出结果看,长的是一模一样,难道这里的l1和l2真的没有区别吗?这里再介绍一个常用函数------id(x),它表示括号内变量所在的内存地址

我们分别来看一下l1,l2内子list的内存地址情况:

震惊!这里可以看到,l1的三个子list的内存地址居然一模一样!而l2的子list所在的内存地址各不相同!??

我们队l1,l2的子list分别进行extend操作,如下:

我们本来只是对l1/l2的第二个子list进行extend操作,但结果却是l1的三个子数组都受到了影响,而l2是只有第二个子数组实现了extend操作。

再分别看此时各子list的内存地址:

与刚才的结果一致,l1的三个子数组位于同一段内存地址,l2则各不相同。

用个直接使用“=”对l1的子list进行赋值呢?

此时,只有被赋值的l1[1]成功赋值,另外两个没有变,并且l1[1]的内存地址已经发生变化,而l1[0],l1[2]依然不变

至此可以总结一下原因了:

1.使用*进行list“复制”,其生成的新数组与被复制的数组其实是在同一段内存地址当中,这样的复制方式成为潜复制

2.浅复制进行初始化的结果就是,在对复制之后的对象进行相关操作时,被复制的对象会受到同样的影响,因为他们本质是同一段list,均位于相同的地址

3.使用“=”进行赋值,是将"="后的内容创建到一个新的内存地址当中,并将"="左的变量的地址重新指向"="右产生的新地址当中

具体到解决实际问题,在初始化一个"已知shape,但内部的值待填充"的一个"空"list时,建议使用for循环进行初始化,例如上文提到这个格式,即:

v=[['' for i in range(m)] for j in range(n)]

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。