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]]