初用python 写起来跟js很像,比较爽,不过很快就遇到了坑
l = []d = {'num': 0, 'sqrt': 0}for x in [1, 2, 3]: d['num'] = x d['sqrt'] = x*x l.append(d)print l
注意这里l append进去的是d的引用,而不是另一个独一无二的东西。因此结果应该是
[{'num': 3, 'sqrt': 9}, {'num': 3, 'sqrt': 9}, {'num': 3, 'sqrt': 9}]
l内部有三个d的引用。每当我们修改d,那么d的引用会被相应修改。
而我们想得到的是,从1到3的平方,那么可以采用浅拷贝
l = []d = {'num': 0, 'sqrt': 0}for x in [1, 2, 3]: d['num'] = x d['sqrt'] = x*x l.append(d.copy())print l
这里浅拷贝与深拷贝有什么区别呢?举个栗子(采用copy模块)
m = [1, [2, 2], [3, 3]]n = copy.copy(m)n[1].append(2)print m, n//[1, [2, 2, 2], [3, 3]] [1, 0, [3, 3]]//其实修改的m[1]n[1] = 0print m, n//[1, [2, 2, 2], [3, 3]] [1, 0, [3, 3]]//覆盖了n[1]引用的m[1]n[2].append(3)print m, n//[1, [2, 2, 2], [3, 3, 3]] [1, 0, [3, 3, 3]]//修改m[2]m[1].pop()print m, n//[1, [2, 2], [3, 3, 3]] [1, 0, [3, 3, 3]]//修改m[1],对n没影响了m[2].pop()print m, n//[1, [2, 2], [3, 3]] [1, 0, [3, 3]]//修改m[2],相应的n[2]也被修改。
我们利用浅拷贝拷贝了m后,对象的属性还是引用原来的。因此如果利用下标,修改下标引用的那个子对象,修改的还是原来的对象。
而当我们把n[1]子对象覆盖后,n[1]就跟m没啥关系了。
再看深拷贝
a = [1, 2, 3, 4, ['a', 'b']] #原始对象b = a #赋值,传对象的引用c = copy.copy(a) #对象拷贝,浅拷贝d = copy.deepcopy(a) #对象拷贝,深拷贝a.append(5) #修改对象aa[4].append('c') #修改对象a中的['a', 'b']数组对象print 'a = ', aprint 'b = ', bprint 'c = ', cprint 'd = ', d
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']]
深拷贝把子对象也拷贝了,因此修改原对象的子对象,会影响浅拷贝的子对象,而不会影响深拷贝。
总结来讲?copy拷贝一个对象,但是对象的属性还是引用原来的,deepcopy拷贝一个对象,把对象里面的属性也做了拷贝,deepcopy之后完全是另一个对象了。
参考?http://luchanghong.com/python/2012/09/21/the-differences-between-copy-and-deepcopy-in-python.html
原文地址:python的浅拷贝与深拷贝, 感谢原作者分享。 追寻爱情,然后发现,爱,从来就是一件千回百转的事。