深浅拷贝在python中经常使用,其区别的外在表现是:
使用浅拷贝,当原容器对象中可变对象中有元素发生变化,拷贝得到的对象也会变化。而使用深拷贝时,不会有这种问题。
听起来有一点难理解,看例子比较直观:
浅拷贝
>>> list1 = [['a', 'b'], 1, 2]
>>> list3 = copy.copy(list1)
>>> list3
[['a', 'b'], 1, 2]
>>> list1[0][0] = 'c' #修改lsit1
>>> list3
[['c', 'b'], 1, 2] #list3也变了
深拷贝
>>> list1 = [['a', 'b'], 1, 2]
>>> list3 = copy.deepcopy(list1)
>>> list1[0][0] = 'c' #修改list1
>>> list3
[['a', 'b'], 1, 2] #list3没有变
但是为什么会这样,可以由下图解释:
当我们声明list1 = [['a', 'b'], 1, 2]时,计算机做了这些事:
1、在内存中开辟一段空间,用来存放字符a,b和数字1,数字2
2、在内存开辟一段空间,用来存放一个列表,我们称为list2。list2中存放两个指针,分别指向字符a和b
3、在内存开辟一段空间,用来存放一个列表lsit1,list1中存放三个指针,分别指向list2,数字1和数字2
当执行浅拷贝lsit3 = copy.copy(list1)时,计算机开辟一段内存给list3,list3保存三个指针,分别指向list2,数字1和数字2。当执行list1[0][0] = 'c'时,list2对象修改了,而list3的第一个指针指向list2,所以我们看到list3的第一个元素也变了。
当执行深拷贝lsit4 = copy.copy(list1)时,计算机开辟一段内存给list4,和浅拷贝不同的是,计算机同时开辟一段空间给新的列表,我们称为lsit5。list5中保存2个指针,分别指向字符a和b。
同时list4保存三个指针,分别指向list5,数字1和数字2。此时,当执行list1[0][0] = 'c'时,list2对象修改了,但list4的第一个指针指向list5,list5并没有修改,所以list4没有改变。
总结:深拷贝会把可变对象也拷贝一份,而浅拷贝不会。
上面例子中说的是列表(可变对象)的拷贝,那对于元组,字符等不可不对象呢?
答案是,对不可不对象,其实不存在深浅拷贝的问题。无论怎么拷贝,效果都是新建立一个指向不可变对象的指针而已。
>>> a = 'f'
>>> b = copy.copy(a)
>>> id(a)
4302389968
>>> id(b)
4302389968
>>> c = copy.deepcopy(a)
>>> id(c)
4302389968
>>>
>>> d = a
>>> id(a)
4302389968