个人理解一共是有三种拷贝:拷贝(赋值),浅拷贝,深拷贝
以a = [1, 2, 3, 4, ['a', 'b']]
为例;
import copy
a = [1, 2, 3, 4, ['a', 'b']]
b = a #赋值。传对象的引用
c = copy.copy(a) #对象拷贝,浅拷贝
d = copy.deepcopy(a) #对象拷贝,深拷贝
e = a[:] #利用分片操作进行拷贝(浅拷贝)
a.append(5) #改动对象a
a[4].append('c') #改动对象a中的['a', 'b']列表子对象
print 'a = ', a
print 'b = ', b
print 'c = ', c
print 'd = ', d
print "e = ", e
执行结果:
a = [1, 2, 3, 4, ['a', 'b', 'c'], 5]
b = [1, 2, 3, 4, ['a', 'b', 'c'], 5]
c = [1, 2, 3, 4, ['a', 'b', 'c']]
d = [1, 2, 3, 4, ['a', 'b']]
e = [1, 2, 3, 4, ['a', 'b', 'c']]
首先了解一下python各数据类型在内存中的存储方式:
基本类型 :
基本类型在内存中分别占有固定大小的空间,他们的值保存在栈空间,我们是通过按值来访问的。
引用类型 :
引用类型,值大小不固定,栈内存中存放地址指向堆内存中的对象。是按引用访问的。
栈内存中存放的只是该对象的访问地址,在堆内存中为这个值分配空间。由于这种值的大小不固定,
因此不能把它们保存到栈内存中。但内存地址大小的固定的,因此可以将内存地址保存在栈内存中。
这样,当查询引用类型的变量时, 先从栈中读取内存地址, 然后再通过地址找到堆中的值。对于这种,
我们把它叫做按引用访问。
浅拷贝只复制指向某个对象的引用地址,而不复制对象本身(只复制一层对象的属性),新旧对象还是共享同一块内存。
但深拷贝会另外创造一个一模一样的对象,新对象跟原对象不共享内存,修改新对象不会改到原对象。
浅复制只复制一层对象的属性,而深复制则递归复制了所有层级。
分析:b赋值:是对a对象的内存地址的引用,两者必然相同
c浅拷贝:把a对象本身完全拷贝,开辟新的内存空间,如果a中有子对象是可变类型,浅拷贝也只拷贝子对象的引用地址,故在子对象可变类型值改变后,浅拷贝对象也改变。切片原理就是浅拷贝,同上
d深拷贝:不仅把a对象完全拷贝,而且对a的子对象也完全拷贝。之后a的任何元素改变都不影响d的值,两个已经是完全独立的对象了。
*****总结:*****拷贝从引用类型出发,依据程度的不同,呈现不同的效果!