深拷贝和浅拷贝
都是对象的拷贝,都会生成一个看起来相同的对象,他们本质的区别是拷贝出来的对象的地址是否和原对象一样,也就是地址的复制还是值的复制的区别。
深拷贝和浅拷贝需要注意的地方就是可变元素的拷贝:
在浅拷贝时,拷贝出来的新对象的地址和原对象是不一样的,但是新对象里面的可变元素(如列表)的地址和原对象里的可变元素的地址是相同的,也就是说浅拷贝它拷贝的是浅层次的数据结构(不可变元素),对象里的可变元素作为深层次的数据结构并没有被拷贝到新地址里面去,而是和原对象里的可变元素指向同一个地址,所以在新对象或原对象里对这个可变元素做修改时,两个对象是同时改变的,但是深拷贝不会这样,这个是浅拷贝相对于深拷贝最根本的区别
也可以这样理解:
深拷贝就是完全跟以前就没有任何关系了,原来的对象怎么改都不会影响当前对象
浅拷贝,原对象的list元素改变的话会改变当前对象,如果当前对象中list元素改变了,也同样会影响原对象。
通常复制的时候要用深拷贝,因为浅拷贝后,两个对象中不可变对象指向不同地址,相互不会改变,但是两个对象中的可变元素是指向相同的地址,一个变了,另一个会同时改变,会有影响(list是可变对象)。
如果要让原list和copy list没有影响怎么办?
**用深拷贝,**拷贝后完全开辟新的内存地址来保存之前的对象,虽然可能地址执行的内容可能相同(同一个地址,例如’s’),但是不会相互影响。
什么是可变对象,什么是不可变对象:
可变对象是指,一个对象在不改变其所指向的地址的前提下,可以修改其所指向的地址中的值;
不可变对象是指,一个对象所指向的地址上值是不能修改的,如果你修改了这个对象的值,那么它指向的地址就改变了,相当于你把这个对象指向的值复制出来一份,然后做了修改后存到另一个地址上了,但是可变对象就不会做这样的动作,而是直接在对象所指的地址上把值给改变了,而这个对象依然指向这个地址。
>>> import copy
>>> a=[1,2,3,"a",["b","c"]]
>>> b=a
>>> a
[1, 2, 3, 'a', ['b', 'c']]
>>> b
[1, 2, 3, 'a', ['b', 'c']]
>>> id(a)
41875208
>>> id(b)
41875208
>>> c=copy.copy(a)
>>> c
[1, 2, 3, 'a', ['b', 'c']]
>>> c[4].append("d")
>>> c
[1, 2, 3, 'a', ['b', 'c', 'd']]
>>> a
[1, 2, 3, 'a', ['b', 'c', 'd']]
>>> d=copy.deepcopy(a)
>>> d
[1, 2, 3, 'a', ['b', 'c', 'd']]
>>> d[4].append("x")
>>> d
[1, 2, 3, 'a', ['b', 'c', 'd', 'x']]
>>> a
[1, 2, 3, 'a', ['b', 'c', 'd']]
>>> d[0]="m"
>>> d
['m', 2, 3, 'a', ['b', 'c', 'd', 'x']]
>>> a
[1, 2, 3, 'a', ['b', 'c', 'd']]
>>> c
[1, 2, 3, 'a', ['b', 'c', 'd']]
>>> a
[1, 2, 3, 'a', ['b', 'c', 'd']]
>>> c[0]=100
>>> c
[100, 2, 3, 'a', ['b', 'c', 'd']]
>>> a
[1, 2, 3, 'a', ['b', 'c', 'd']]
>>> c.append("e")
>>> c
[100, 2, 3, 'a', ['b', 'c', 'd'], 'e']
>>> a
[1, 2, 3, 'a', ['b', 'c', 'd']]
>>> c[4].append("e")
>>> a
[1, 2, 3, 'a', ['b', 'c', 'd', 'e']]
>>> c
[100, 2, 3, 'a', ['b', 'c', 'd', 'e'], 'e']
>>>