只看楼主 #交流分享#-列表的复制
-
阅读:507 回复:4 2022-04-11 08:20:47
-
涉及 赋值 深浅拷贝 以及 可变对象与不可变对象知识。
赋值操作并不是往一个容器里装数据,而是往一个数据上贴标签
list 中的元素保存的其实是一个索引,当你copy时,只是复制了一份索引,指向的内容还是同一份。
虽然lst和lst2第一个位置都指向数字2,但是数字是不可变对象,所以两个2互不影响,所以图中就不指出来了。
当列表中全是数字(不可变对象) 那么深浅拷贝就没什么区别了。如你的例子2。
2022-04-11 10:34:35
-
首先我们要知道,数组的“值”其实就是首位数据的地址,如下图第8、9行,输出数组的值和数组第1位的引用,能发现它俩是同样的。其次我们又知道,数组是一个连续存储的单位,看下图第9、10行,输出数组第1、2位的引用,发现它俩就是差了4,正好是一个int的字节大小。
那么我们再来看这里的例子。
origin为原数组,assign为直接赋值原数组。
赋值就是对象的引用,将origin数组的首地址直接给到assign数组,所以操作的时候其实是找到同一片数据的,因此无论是修改了assign里面的数据还是origin里面的数据,两个数组都会同步修改的。
而copy1=origin[:],大家注意这里的[:]。我们都知道,[:]代表了列表迭代,默认参数是从头开始到列表尾,步长为1,也就是整个列表。也就是说,copy1=origin[:]这个语句,我们把它展开写写,它应当表达为:
它是自带一个循环+赋值的。那么答案就很清晰了,为什么加上了[:],修改origin或者copy1都不会对另一个产生影响呢?因为它根本不涉及地址或者说引用,就是一个纯纯的数字,那这个数字改成什么样,都和另一个数组没啥关系。正如上图中第14、15行,第四个例子所示。
那么为什么会出现顾老师所提到的第三张图中的情况呢?我们来看二维列表,列表里的每一项都是一个列表,之前我们说了,列表的值其实就是一个地址,所以用这一遍for循环赋值之后,新列表中的每一项,也都是原列表中的每一个子列表的首地址,又指到同一片数据去了!所以改变二维列表里的数据,两者都随之变化了。
可以观察上图中的第11、12行,对应的第三个例子。修改copy1的第2项的第2项,copy1的第2项就是origin的第2项的地址,所以他们指向的是同一片区域,origin也被修改了。再加上assign是直接赋值origin的,origin的第2项和assign的第2项也是指向同一片区域的,所以还顺便把assign也给改了。
2022-04-11 11:55:20