浅拷贝(shallow copy)和深拷贝(deep copy)

记得面试的时候面试官问我浅复制和深复制有什么区别。只用过python里可变数据类型的copy函数的我一脸懵逼,xjb说了一点,结果自然惨不忍睹。。我回来一查,原来他说的是copy库。。敲里吗啊,copy库又不是一定要用,老子也不是学计算机的,哪知道这么细。。哎,终究是自己才疏学浅,怪不得别人。


python中的unhashable数据类型都自带copy函数。这里的copy其实是所谓的浅拷贝,什么是浅拷贝呢?

这就涉及到了python的赋值机制了。

看一个例子:

x=[1,2,[3,4]]

python在生成这个列表的时候先为1,2,3,4分配内存pos1,pos2,pos3,pos4,然后为列表[3,4]分配一段内存 pos5 ,它包含2个位置,分别指向内存pos3,pos4。然后为列表[1,2,[3,4]]分配一段内存 posa,它包含3个位置,分别指向内存pos1,pos2,pos5, 最后再让变量 x 指向这个列表。


                                            内存                                               命名空间

                           pos1 : PyInt(1)  (不可变)                                                 
                           pos2 : PyInt(2)  (不可变)                                   x : posa
                           pos5 : PyList(pos3,pos4)(可变)                    
                                    posa : PyList(pos1, pos2, pos5)  (可变)                          

                                    pos6 : Pyint(5) (不可变)                                                

y=x.copy()

当python接收到浅拷贝命令后,为拷贝的列表分配一个新的内存posb,它同样也包含3个位置,分别指向内存pos1,pos2,pos5。

当列表x中的元素改变时:

x.append(5) // python为5分配一个新的内存pos6,此时pos0包含4个位置,分别指向内存pos1,pos2,pos5,pos6。

或者

x[0]=5         // python为5分配一个新的内存pos6,此时pos0包含3个位置,分别指向内存pos2,pos5,pos6。

这时候拷贝列表的内存还是指向pos1,pos2,pos5,也即不会发生变化。

当x中的元素的元素发生改变时:

x[2][0]=0

python为0分配一个新的内存,pos5的指向也会改变,但是posa,posb依然包含三个位置,分别指向pos1,pos2,pos5,也即x=y=[1,2,[0,4]


浅拷贝只拷贝父对象,不拷贝对象的子对象。因此当父对象改变时,拷贝不变。当子对象改变时,浅拷贝跟着变。

还可以导入copy库来创建浅拷贝

方法是

import copy

y=copy.copy(x)


创建深拷贝:

y=copy.deepcopy(x)


深拷贝除了拷贝父对象,还拷贝对象的子对象。用上面的例子来讲,不同之处在于深拷贝为元素[3,4]又分配了一个新的内存,指向pos3,pos4,这样,当列表x无论改变其元素还是其元素的子元素都不会影响深拷贝列表y的内存指向,也即y与x相互独立了。


猜你喜欢

转载自blog.csdn.net/keyboardwarrior/article/details/79033195
今日推荐