参考链接: http://www.cnblogs.com/wilber2013/p/4645353.html
Python中的对象赋值,浅拷贝,深拷贝是不同的三个方法,下面谈下他们之间的差异。
对象赋值
先看代码:
分析一下:
- 首先创建了一个名为a的变量,这个对象指向一个list对象,我们使用列表生成式可以看到a中所有元素对象的地址。
- 然后通过a变量对b变量进行赋值,那么b将指向a对应的对象(内存地址),也就是说“b就是a,b[i]就是a[i]”,这里可以理解成为在python中,对象的赋值都是对象引用(内存地址)的传递。
- 由于a和b都指向同一个对象,所以对a的改动也会体现在b上,反之也是这样。
这里需要注意的是,因为字符串,元组等等是不可变的类型,所以修改的时候会替换旧的对象,产生一个新的地址。(在例子中是’139697967318608’变成了’139697936776808’)
浅拷贝
一段代码的例子:
分析代码:
- 首先使用一个变量a,指向一个list类型的对象。
- 然后导入copy模块,使用模块中的浅拷贝函数copy(),对a指向的对象进行浅拷贝,然后拷贝生成新的对象赋值给c变量。
- 浅拷贝会常见一个新的对象,这个例子中c并不是a
- 但是对于对象中的元素,浅拷贝只能使用原始的元素的引用(内存地址),也就是说‘c[i]就是a[i]’
- 当对a进行修改的时候,因为a[0]是字符串类型,是不可变的类型,所以a[0]被修改以后会生成一个新的对象,也就是从原来的’140327519614376’变成现在的’140327519616896’
- 但是a[2]是一个列表,是可变的数据类型,对a[2]修改的时候,并不会生成新的对象,也就是不会占用新的内存地址,(140327519625416一直没变)所以对于a[2]的改变同样会在c上面体现。
深拷贝
还是先看代码:
分析代码:
- 首先还是一个变量a,指向list对象。
- 然后使用copy模块中的深拷贝函数deepcopy()进行深拷贝,将拷贝生成的新对象赋值给d
- 深拷贝会创建一个新的对象,这一点和浅拷贝是类似的。
- 但是和浅拷贝不同的是,深拷贝对于对象中的元素,深拷贝都会重新生成一份,而不是简单的使用原始元素的引用(内存地址),在上面的代码中,a[2]指向的是‘140327519625416’,但是d[2]指向的是’140327488917704’
- 在修改a里面的元素的时候,由于a[0]是不可变的字符串类型,那么a[0]修改会生成一个新的对象,所以修改a[0]并不会影响d,而改变a[2]的时候,因为是对a深拷贝之后赋值给d,所以a[2]和d[2]指向的是不同的对象,所以修改a[2]并不会影响d[2]
一些特殊的例子:
对于非容器类型,比如数字,字符串和其他原子类型的对象,没有拷贝这一说,也就是’obj is copy.copy(obj)’,’obj is copy.deepcopy(obj)’.
如果元组对象只包含了原子类型的对象,不能进行深拷贝。