当前位置: 首页 > 科技观察

学习Python一年,这次终于弄懂了浅拷贝和深拷贝

时间:2023-03-16 14:13:05 科技观察

学习Python一年了,这次终于明白了浅拷贝和深拷贝,用自己的理解写了这么一篇文章。当有人提到Python中的复制操作时,你会不会立马站起来说:“我会”,于是你就有了如下操作:importcopyx=copy.copy(y)#ShallowcopyIknowx=copy.deepcopy(y)#我是来深拷贝的。浅拷贝和深拷贝有什么区别?你能告诉我吗?1.从引用vs.拷贝开始首先我们要搞清楚什么是对象引用和对象拷贝(replication)。对象引用Python中对对象的赋值其实就是对对象的引用。在创建对象并将其赋值给另一个变量时,Python不会复制对象,而只会复制对象的引用。>>>a=1>>>b=a>>>id(a)==id(b)True>>>x=[1,2,3]>>>y=[x,4]>>>>x[1,2,3]>>>y[[1,2,3],4]>>>>>>>>id(x)==id(y)False>>>id(x)==id(y[0])True如果这个过程不明白,可以看下图:当我们对x列表进行操作时,会发现y中发生了意想不到的事情:>>>x[1]=2020>>>y[[1,2020,3],4]由于列表是可变的,当列表对象x被修改时,对象y中对x的引用也会改变。因此,重要的是,当我们就地修改可变对象时,它可能会影响程序中其他地方对同一对象的其他引用。如果不想这样做,则需要明确告诉Python复制对象。对象复制如果需要复制,可以进行以下操作:无限制切片表达式(L[:])工厂函数(如list/dir/set)字典复制方法(X.copy())复制标准库模块(importcopy)比如假设有一个列表L和一个字典D:>>>L=[2019,2020,2021]>>>D={'1':2019,'2':2020,'3':2021}>>>>>>A=L[:]#区分A=L或A=List(L)>>>B=D.copy()#区分B=D>>>A[2019,2020,2021]>>>B{'1':2019,'2':2020,'3':2021}这样定义之后,当你修改A和B时,会发现原来的L和B没有变化D产生影响,因为,这是对象的副本。>>>A[1]='快乐'>>>B[3]='今天'>>>L,D([2019,2020,2021],{'1':2019,'2':2020,'3':2021})>>>A,B([2019,'快乐',2021],{'1':2019,'2':2020,'3':2021,3:'今天'})上面的列表和字典的拷贝操作默认是浅拷贝:字典的浅拷贝可以使用dict.copy()方法来完成,列表的浅拷贝可以通过分配整个列表的一部分来完成列表,例如,copied_list=original_list[:]。说到这里,问题来了?什么是浅拷贝?浅拷贝对应的深拷贝怎么解释?2.浅谈浅拷贝和深拷贝官方文档定义:浅拷贝和深拷贝的区别只与复合对象(即包含其他对象的对象,如列表或类的实例)有关:浅拷贝会构造一个新的复合对象,并(尽可能)将在原始对象中找到的引用插入其中。深拷贝构造一个新的复合对象,然后递归地插入在原始对象中找到的对象的副本。浅拷贝浅拷贝:复制最外层的对象本身,而内部的元素只是复制一个引用。也就是把对象再复制一遍,但是我不复制对象中引用的其他对象。通俗地说就是:有一个