[Python]copy模块学习 -- 深拷贝和浅拷贝

来源:互联网 发布:词典 知乎 编辑:程序博客网 时间:2024/05/21 09:13
Python拷贝对象常用的模块是copy模块,这个模块有两个方法,copy,deepcopy也就是常说的浅拷贝和深拷贝
那么2种拷贝有什么不同呢? 今天就来研究下,这里研究对象是否相同用的是id()方法,也可以用is方法来判断


浅拷贝有几种方法:

第一种就是使用copy.copy()方法

>>> import copy>>> a = [[1,3]]>>> b = copy.copy(a)>>> print id(a),id(b) #a b引用的id不同48701112 48720992>>> id(a[0]) #但是a,b内元素的id是相同的 48697992>>> id(b[0])48697992


第二种是切片浅拷贝

>>> print id(a[0]),id(c[0])48697992 48697992


第三种就是list,dict,set,tuple的构造函数来做copy

>>> print id(a[0]),id(d[0])48697992 48697992>>> a[0] == b[0]True>>> a[0] is d[0]True

深拷贝只有用copy的deepcopy方法了

>>> e = copy.deepcopy(a)>>> a[0] == e[0]True>>> a[0] is e[0]False>>> print id(a[0]),id(e[0]) #这次我们发现深拷贝后的e的第一个元素id和原来的a的子元素的id不同了48697992 48692160

引用python核心编程的一段话来总结下 
第一,非容器类型(比如数字,字符串和其他"原子"类型的对象,像代码,类型和 xrange 对象等)没有被拷贝一说,浅拷贝是用完全切片操作来完成的.
第二,如果元组变量只包含原子类型对象,对它的深拷贝将不会进行.



那这种不同的拷贝会给我们带来怎么样的奇怪的问题呢?来看看python核心编程中一个很好的例子
加入说我们用 person = ['name',['saving',100.00]]来表示一个人和他的存款,假设现在有2对夫,我们来看看不同拷贝造成的影响

案例

家庭一 :浅拷贝

>>> person = ['name',['saving',100.00]]>>> husband1 = person>>> wife1 = person>>> print husband1,wife1['name', ['saving', 100.0]] ['name', ['saving', 100.0]] #现在我们看到2个人的账户中都是100块>>> husband1[1][1] = 50.00 #现在丈夫取走50 >>> print husband1,wife1['name', ['saving', 50.0]] ['name', ['saving', 50.0]] # 怎么妻子也是50了呢

也就是说其实夫妻是共同的一个账户,一个人的变化也会影响到另一个人的金额的变化


家庭二:深拷贝

>>> person = ['name',['saving',100.00]]>>> husband2 = person>>> wife2 = copy.deepcopy(person)>>> husband2[0] = 'Jack'>>> wife2[0] = 'Rose'>>> print husband2,wife2['Jack', ['saving', 100.0]] ['Rose', ['saving', 100.0]] #2个人都是100块>>> husband2[1][1] = 50.00  #丈夫取出50 >>> print husband2,wife2['Jack', ['saving', 50.0]] ['Rose', ['saving', 100.0]] #妻子还是100

深拷贝之后丈夫和妻子的账户都是独立的,谁也不会影响谁


看到差别了吗,如果我们想让一个容器类型的一个容器类型的子元素不被所有引用对象共享,就要使用深拷贝了。