深拷贝、浅拷贝
问题处理:
- 需要把 :a = [1,1,2,3,4,5,1,4,5,6,8,9],里面的奇数全部删除
a = [1,1,2,3,4,5,1,4,5,6,8,9] for i in a: if i % 2 !=0: a.remove(i) print(a) #循环删list会导致下标错乱
结果:[1, 2, 4, 1, 4, 6, 8]
我们发现,取值的值并不对,1并不是偶数,并没有删除,因循环是以取下标的方式删除的,第二次循环是时下标为0的就会跳过,因为第一次已经循环过了,第二次就会以下标为1的进行循环,就是以2来开始循环,把第二个1跳过了
所以,我们可以使用两个同样的list,这样会解决此问题,可以不用考虑到下标错乱,因为是每次都是依次循环的
a = [1,1,2,3,4,5,1,4,5,6,8,9] a2 = [1,1,2,3,4,5,1,4,5,6,8,9] for i in a2: if i % 2 !=0: a.remove(i) print(a) 结果:[2, 4, 4, 6, 8]
浅拷贝:
——使用copy模块里面的copy方法实现,改变原始对象中为可变类型的元素的值,会同时影响拷贝对象,改变原始对象中为不可变类型的元素的值,不会响拷贝对象
a = [1,1,2,3,4,5,1,4,5,6,8,9] a2 = a print('a的ID:',id(a)) print('a2的ID:',id(a2)) for i in a2: if i % 2 !=0: a.remove(i) print(a) 结果: a的ID: 18230152 a2的ID: 18230152 [1, 2, 4, 1, 4, 6, 8]
我们发现,结果还是不对的,因为 a2 = a,是把 a 的值赋值给了 a2,这个时候他们两个的内存地址还是一样的,删除的时候相当于还是删除的一个list,这种方式我们叫作【浅拷贝】。
深拷贝:
——copy模块里面的deepcopy方法实现。深拷贝,除了顶层拷贝,还对子元素也进行了拷贝原始对象和拷贝对象所有的可变元素地址都不一样了
*只有 copy.deepcopy 在Python属于是深拷贝
import copy a = [1,1,2,3,4,5,1,4,5,6,8,9] a2 = copy.deepcopy(a) print('a的ID:',id(a)) print('a2的ID:',id(a2)) for i in a2: if i % 2 !=0: a.remove(i) print(a) 结果: a的ID: 18515592 a2的ID: 18513992 [2, 4, 4, 6, 8]
这时我们可以看到处理出的数据是对的,并且 a2 和 a 的ID已经不一样了,这种拷贝方式,我们叫作是【深拷贝】
巩固练习(一):
a = [1,1,2,3,4,5,1,4,5,6,8,9] a2 = a.copy() a3 = copy.copy(a) a4 = copy.deepcopy(a) print('a的ID:',id(a)) print('a2的ID:',id(a2)) print('a3的ID:',id(a3)) print('a4的ID:',id(a4)) 结果: a的ID: 18716680 a2的ID: 18714696 a3的ID: 18323208 a4的ID: 497943056
我们可以看到上边的结果,每个结果的ID地址其实是不一样的,那这种是不是属于是深拷贝呢?答案是:不是的,只有copy.deepcopy()属于是深拷贝,dict.copy也是浅拷贝
巩固练习(二):
import copy a = ['12',2,3,4,{'key':'key1'}] a2 = a a3 = copy.deepcopy(a) a4 = a.copy() a.pop(1) a[-1]['key1'] = 'liangcailian' print('a2的结果:',a2) print('a3的结果:',a3) print('a4的结果:',a4) 结果: a2的结果: ['12', 3, 4, {'key1': 'liangcailian', 'key': 'key1'}] a3的结果: ['12', 2, 3, 4, {'key': 'key1'}] a4的结果: ['12', 2, 3, 4, {'key1': 'liangcailian', 'key': 'key1'}]
我们可以从结果中看出 a3 和 a4 的结果已经不一样了,所以说 除了copy.deepcopy()是深拷贝外,其他的拷贝方式都是浅拷贝,当数据是多维数据嵌套时,就会正常处理不了啦。
总结:
- copy出来之后,如果内存地址不变,肯定是浅拷贝
- copy.deepcopy , 肯定是深拷贝,而且只有这一种,拷贝时无论是什么样的地址,数据都会正常处理
- 其他的拷贝方式,即使是内存地址变了,有些数据会正常处理,但处理的数据比较深时,就会正常处理不了啦
- 深拷贝是将对象本身复制给另一个对象。这意味着如果对对象的副本进行更改时不会影响原对象
- 浅拷贝是将对象的引用复制给另一个对象。因此,如果我们在副本中进行更改时会影响原对象
- 深浅拷贝都是对源对象的复制,占用不同的内存空间
- 不可变类型的对象,对于深浅拷贝毫无影响,最终的地址值和值都是相等的
- 可变类型的对象:值相等,地址不相等
(1)什么时候使用浅拷贝
——复制一个变量时, 数据b 拷贝 数据a 的数据,拷贝过来的 数据b变了,是没关系的,这时可以使用浅拷贝
(2)什么时候使用深拷贝、
——复制一个变量时,数据a 和 数据b 需要拷贝的完全一致,这时需要使用到深拷贝才可以
本文来自博客园,作者:他还在坚持嘛,转载请注明原文链接:他还在坚持嘛 https://www.cnblogs.com/brf-test/p/13337985.html