您的位置:首页 > 编程语言 > Python开发

Python学习笔记——深拷贝与浅拷贝

2017-07-21 15:26 281 查看

浅拷贝



解读:

开辟空间存放[11,22,33],然后将其地址放在a中,执行b = a后,将[11,22,33]的地址也放在b中。这样就完成了浅拷贝。


浅拷贝,拷贝后两者is和==都为true

并且无论是a变了还是b变了,只要是不涉及开辟新空间的情况下,都直接影响另一个变量,使得a和b的is和==返回值都为true。

深拷贝



这里可以看到深拷贝的命令需要import copy,然后调用copy.deepcopy()(真·深拷贝)

程序解读:

开辟空间A存放[11,22,33],然后将其地址放在a中,在执行b = copy.deepcopy(a)后,py君又开辟了新空间B,直接将原来A空间里的[11,22,33]拿了过来放到B空间中,然后把B控件的地址给了b。这样就完成了深拷贝。

深拷贝后,两者 == 为真,is为假,数据更新互不影响。

拓展

帮助理解浅拷贝与深拷贝:

请看如下代码



d 是 c 的浅拷贝

e 是 c 的深拷贝

f 是 c 的拷贝

经过刚才的讲解,d应该已经不用讲了,与c完全相同。

我们来看深拷贝的e

我们更改a.append(4)

看深拷贝的e怎么变?



就像刚才说的,深拷贝后,c与e的数据完全独立,不会互相影响。

稍微解读下,



在执行e = copy.deepcopy(c)时,py君看见c中放的是地址,又发现此地址里对应的空间中存放着不是不可变类型的数据,就开辟一个新空间X将c中的数据拿过来放到空间X中,正要拿的时候,发现c中存放着两个地址,这时候py君就有开辟了一个新空间Y,去c中第一个地址里去拿数据放在空间Y中,然后把空间Y的地址存放在了空间X中,然后又开辟了新空间Z将c中第二个地址里去拿数据存放在空间Z中,之后把空间Z的地址放到了空间X中,最后,将空间X的地址给e。到此结束此操作。

这一些列操作,其实就是递归,如果遇见不是数据而是地址了,就在调用一次自己。

就像上面所说的,e = copy.deepcopy(c),因为c是列表长度是2

就可以理解为e[0] = copy.deepcopy(c[0])和e[1] = copy.deepcopy(c[1])的集合。

(其实是e[0] = copy.copy(c[0])和e[1] = copy.copy(c[1]))

下面是拷贝的f

用同样的方法,改变a.append(4)

结果发现:





py君,你在逗我,这什么鬼?

这其实就是copy.copy方法。

我们来画个图:



看完这个图,会不会有一点点明白了?

我再稍微解释下我的理解:

f = copy.copy(c),py君一看c里放着是地址,看地址指向的空间中里存放着是不是不可变类型,一看存放的也是地址,直接开辟新空间X,然后将c指向的控件里的东西全部移动到空间X中,然后把空间X地址放在f中。操作完毕。

拷贝操作,看见地址a,直接开辟也仅开辟一次空间X。不管是地址a所对应的空间中是地址还是数据直接放入空间X。

我就怕我越解释越晕。TAT

总结

浅拷贝、拷贝、深拷贝

浅拷贝 a = b 在不涉及开辟新空间的情况下,数据完全同步。

拷贝 a = copy.copy(b) 遇见一次地址,开辟且仅开辟一次新空间,将此地址中的数据/地址直接放入新空间中,新空间的地址放入新变量中。

深拷贝 a = copy.deepcopy(b) 只要遇见一次地址,就开辟一次新空间(无次数限制),本质上就是拷贝方法的递归。

当然如果在用拷贝方法的时候,被拷贝对象存放的地址所对应的空间中是不可变类型。那就自动变成浅拷贝。不可变类型:string,integer,tuple

以上。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  python