先来道题热热身
<code>a = ('a'
,'b'
,'c'
) c =copy
.copy
(a) d =copy
.deepcopy(a)if
c == d:"c和d的值相等"
)if
id(c) == id(d):"c和d的地址相等"
)/<code>
想想最后打印的是什么?
什么是深拷贝和浅拷贝
深拷贝,就是在对某个对象进行拷贝的时候,如果这个对象持有其他对象的引用,在拷贝的时候会将要拷贝的对象以及引用的对象,一起拷贝。
而浅拷贝只拷贝当前对象和持有的索引,不拷贝索引指向的对象。举个例子说明一下,比如当前有个列表a = [1,2,3], b = [3,4,a],[3,4,a]对象持有了[1,2,3]对象的引用,在对b进行深拷贝的时候,会将a对象一起拷贝一份,而浅拷贝的时候则不会。
<code>a
= [1
,2
,3
]b
= [4
,5
,6
,a]/<code>
对b进行浅拷贝
<code>/<code>
这个时候对a对象进行修改,会影响c
<code>a.append(8)
c
[4,
5
,
6
,
[1,
2
,
3
,
8
]]
/<code>
对b进行深拷贝之后,再对a进行修改,则不会影响到d
<code>d
=
copy.deepcopy(b)
d
[4,
5
,
6
,
[1,
2
,
3
,
8
]]
a.append(66)
d
[4,
5
,
6
,
[1,
2
,
3
,
8
]
/<code>
当深浅拷贝遇到可变与不可变对象时会发生什么
上面用列表这种可变数据结构举例,再来看一下元组这种不可变结构,在进行深浅拷贝时定的现象。
<code>a = (1
,2
,3
) b =copy
.copy
(a) c =copy
.deepcopy(a)4502776896
4502776896
4502776896
/<code>
从结果中发现,a、b、c的内存地址大都是一样,所以在对不可变对象进行拷贝的时候,无论是浅拷贝还是深拷贝,都没有重新在内存中开辟新的地址,都只是对原对象增加了一个引用。
那如果不可变对象汇总包含有对可变对象的引用又会是怎么样呢?
<code>a1 = [1
,2
,3
] a = (1
,2
,3
, a1) b =copy
.copy
(a) c =copy
.deepcopy(a)4502730288
4502730288
4503232240
/<code>
b是浅拷贝生成的对象和原对象a的内存地址是一样对的,c是深拷贝生成的对象,发现内存地址和原对象a的地址是不一样的。
也就是说如果不可变对象中持有了可变对象的引用,在进行深拷贝的时候会在内存中开辟新的地址存放对象。
回到文章开头提出的问题,是对不可变对象进行拷贝,而且不可变对象中并没有持有可变对象的引用,所以两个print语句都会执行。