Python学习之深浅copy

Posted by 404player on May 23, 2020

看过很多哥们的Python开发岗面试经历,发现有一个问题经常被问到:深浅copy的区别。所以特意去了解了解,并做了总结。

1.浅copy

首先我们先定义一个嵌套列表:

person = ['name',['saving',100]]

然后我们先来看看Python中浅copy的几种写法:

import copy  
p1 = copy.copy(person) #浅copy    
p2 = person[:] #浅copy    
p3 = list(person) #浅copy  

我们通过例子可以看到,进行浅copy一共有三种方式:
① 使用copy模块的copy方法进行复制
② 对要浅copy的列表进行一次完全索引
③ 使用工厂函数list,并以列表为参数

好!方法我们懂了,接下来就要探究什么是浅copy了。

同样我们通过对刚开始定义的列表person进行操作,来说明浅copy的特性。

首先我们先打印一遍p1:

print(p1)

得出的结果是:

['name', ['saving', 100]]

这个时候我们对person进行修改

person[0]='404player'  
person[1][1]+=200
print(person)

我们再来运行一遍,发现结果变成了:

['404player', ['saving', 300]]

到目前为止,所有运行结果都在我们意料之中。那我们来思考一个问题,对person的改动会不会引起p1的变化呢?

我们尝试打印一下p1,运行结果如下:

['name', ['saving', 300]]  

我们发现一个奇怪的现象,我们并没有对p1进行任何改动,为什么第二层列表的数字就变了呢?

这就涉及到浅copy的原理问题了。

浅拷贝:拷贝了最外围的对象本身,内部的元素都只是拷贝了一个引用而已。也就是,把对象复制一遍,但是该对象中引用的其他对象我不复制

所以,对于浅copy来说,如果出现多层列表,那么对内层列表中所有对象的改动都会直接作用到浅copy生成的对象中,同样,对生成对象中内层列表作改动也会作用到初始对象中

2.深copy

自古有黑即有白,有善即有恶,有浅copy自然也有深copy

深拷贝:外围和内部元素都进行了拷贝对象本身,而不是引用。也就是,把对象复制一遍,并且该对象中引用的其他对象我也复制。

深copy浅copy正好反过来,所以,对多层列表中内层对象的改动并不会影响其他列表。

下面我们看看深copy的用法:

p4 = copy.deepcopy(person)

可以使用上面的例子加以验证,这里就不多赘述了。

3.深浅copy的应用场景

a. 思考一下浅copy的特性,当涉及到一些只需要作全局修改的数据的时候,浅copy可以起到减少内存的作用。因为浅copy复制的是引用,意味着复制内层列表的时候只会复制一个找到列表数据的地址,并不需要多开一块内存来存储新列表。

b. 深copy每复制一个内层列表,都会新开出一块内存来存储,意味着对新内存的改动并不会影响原来的列表。所以在做数据的清洗、修改或者入库的时候,对原数据进行复制一份,以防数据修改之后,找不到原数据。

4. 结语

对深浅copy的总结就做到这,直觉这里面还有很多奥妙,但是太底层的东西我也不太懂了,甚至上文说的也可能有错漏,待发现再以更正,望多多交流。