理解python中的深复制和浅复制 |
您所在的位置:网站首页 › python中列表的复制与拷贝 › 理解python中的深复制和浅复制 |
深复制和浅复制 在python中一切都是对象,每个对象包含了idendity、type 和 value。所以python中的复制语句实际上是添加引用,将内存地址赋予了一个新的别名。 浅复制 浅复制一般出现在非嵌套的对象当中,python中的非容器对象(num,str,其他原子性对象),元组是个例外,后面会讲,对于复制都使用的是浅复制,不分浅复制和深复制。那么对于容器类对象,像list和dict,浅拷贝和深拷贝就有区分了。下面简单的例子: 上述代码中d创建了一个a的浅复制,这时d会新创建一个对象,所以id(a) neq id(b),但是由于a是一个嵌套的容器对象,那么浅复制就不会复制内层内的b的对象,而是复制b的引用。所以id(d[0]) == id(a[0])。这时修改d[0]中的值同样会改变a[0]中的值。 浅复制的几种情况: 使用切片[:]操作使用工厂函数(如list/dir/set)使用copy模块中的copy()函数深复制 深复制相对应与浅复制,浅复制是只有一层的对象复制,其他层都是引用。而深复制则是递归地进行复制,每一层都是对象复制。因此深复制会复制更多东西,占用更多内存,也比浅复制耗时。以下例子: d会完全复制a中的所有内容,因此当d和a是两个完全不同的对象,由于递归复制了所有对象,那么显然d[0]和a[0]也是两个不同的对象,两者不相互影响。 引发的问题 python二维数组初始化 如果使用list来初始化一个全0的数组,便很大可能出现问题,对于一维数组,可以简单地使用a = [0] * 3这里就是使用的浅复制。当二维数组时候就会: >>> a = [[0] * 3] *3 >>> a[0][0] = 1 >>> print(a) [[1, 0, 0], [1, 0, 0], [1, 0, 0]]出现与感觉上相违背的事情,原因是这里的[]*n使用的时浅拷贝,当使用嵌套时,则出现这种错误,上述代码相当于: >>> b = [0] * 3 >>> a = [b, b, b]正确的初始化方式为生成式[[0 for j in range(3)] for i in range(3)]或者使用nunpy。 元组修改问题 元组是不允许修改的,但是如果有以下写法,则是很容易出现问题。例子: a = ([1, 2], 3, 4) a[0] += [5, 6] print(a)当运行以上程序时,首先会报错: TypeError: ‘tuple’ object does not support item assignment,因为元组不允许被修改,但是当打印时会发现:a = ([1, 2, 5, 6], 3, 4),让人觉得很诡异,明明已经报错了,但是元组内的值还是被修改了。这其实因为是+=并不是一个原子操作,先执行的添加,然后再执行的赋值,当赋值时候添加完成了,但是赋值却不被允许。 |
今日新闻 |
推荐新闻 |
CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3 |