Python copy(), deepcopy()

直接赋值

赋值是 b = a: 赋值引用,a 和 b 都指向同一个对象,内存地址相同,即a is b。

赋值不是浅拷贝。

>>> a = [1, 2, 3]
>>> b = a
>>> id(a), id(b)
(140579276041800, 140579276041800)
>>> a, b
([1, 2, 3], [1, 2, 3])
>>> a == b
True
>>> a is b
True
>>> a.append(4)
>>> a, b
([1, 2, 3, 4], [1, 2, 3, 4])

 

copy() 浅拷贝:

创建一组拷贝对象的引用。(浅拷贝会创建一个新对象,新对象和原对象指向同一内存地址,但新对象和原对象本身内存地址不同,即值相等,内存地址不等。例:b = copy.copy(a),a==b,但a is not b)

如果原对象的可变对象改变(list),那么新对象随之改变
如果原对象某位置的不可变对象被替换成其他值,  那么新对象将仍然用原对象的原引用值,不随之改变

也就是说,因为浅拷贝是拷贝对象的引用,可变对象会随着原对象的改变而改变,不可变对象不变。

PS:切片操作是浅拷贝,会生成一个新的对象( id(新对象) != id(原对象) ),新的对象里保存原对象的引用。

例如:

>>> import copy
>>> l
[100, 2, 3, [2, 3, 4]]
>>> l2 = copy.copy(l)
>>> l2
[100, 2, 3, [2, 3, 4]]
>>> l[0]=-1
>>> l
[-1, 2, 3, [2, 3, 4]]
>>> l2
[100, 2, 3, [2, 3, 4]]
>>> l[-1].append(10000)
>>> l
[-1, 2, 3, [2, 3, 4, 10000]]
>>> l2
[100, 2, 3, [2, 3, 4, 10000]]

>>> a = [1,2,3]
>>> id(a)
47973832L
>>> id(a[0])
41902968L
>>> a[0]=5
>>> id(a[0])
41902872L
>>> id(a)
47973832L
>>> a
[5, 2, 3]
>>> c = a[:]
>>> id(c[0])
41902872L
>>> id(a[0])
41902872L
>>> id(a[1])
41902944L
>>> id(c[1])
41902944L
>>> id(c[2])
41902920L
>>> id(a[2])
41902920L
>>> a.append(100)
>>> a
[5, 2, 3, 100]
>>> c
[5, 2, 3]
>>> a[0] = -1
>>> id(a[0])
41903016L
>>> id(c[0])    # a改变了,c仍然引用原对象
41902872L

  

deepcopy() 深拷贝:

对于原对象,不可变类型使用对象引用,可变类型直接复制一份。无论原对象如何改变,深拷贝出来的对象都不变。

>>> l3 = [1,2,3,"abc",[20,30,40]]
>>> l4 = copy.deepcopy(l3)
>>> l4
[1, 2, 3, 'abc', [20, 30, 40]]
>>> l3[0] = 0
>>> l3
[0, 2, 3, 'abc', [20, 30, 40]]
>>> l4
[1, 2, 3, 'abc', [20, 30, 40]]
>>> l3[-1].append(50)
>>> l3
[0, 2, 3, 'abc', [20, 30, 40, 50]]
>>> l4
[1, 2, 3, 'abc', [20, 30, 40]]

  

 

posted @ 2018-03-29 10:56  961897  阅读(238)  评论(0编辑  收藏  举报