python浅拷贝与深拷贝
可以 Python的拷贝,浅拷贝,深拷贝
赋值,浅拷贝,深拷贝在开发中常会用到,但是[拷贝|浅拷贝|深拷贝]只针对可变数据类型,一起看看他们之间的区别吧!
一.赋值
- 其实就是对象的引用(别名)。当创建一个对象,然后把它赋给另一个变量的时候,python并没有拷贝这个对象,而只是拷贝了这个对象的引用
>>> # a, b内存地址相同
>>> # a, b的变化完全同步
>>> a = {1: [1,2,3]}
>>> b = a
>>> print(b) #{1: [1, 2, 3]}
>>> a[1] = [1,2,3,4] #更改a
>>> print(a) #{1: [1, 2, 3, 4]}
>>> print(b) #{1: [1, 2, 3, 4]} # b同步改变
>>> b[1] = [1,2,3,4,5] #更改b
>>> print(a) #{1: [1, 2, 3, 4, 5]} #a也同步改变
>>> print(b) #{1: [1, 2, 3, 4, 5]}
二.浅拷贝
- 拷贝父对象,不会拷贝对象的内部的子对象。
>>> # a, b的内存地址不同,a, b的子对象的内存地址相同
>>> # a, b的子对象的变化同步,a, b的其他变化不同步
>>> import copy
>>> a = {1: [1, 2, 3]}
>>> b = copy.copy(a)
>>> id(a), id(b) #a, b的内存地址不同
(4413393008, 4414925848)
>>> id(a[1]), id(b[1]) #a, b的子对象的内存地址相同
(4414889544, 4414889544)
>>> a[1].append(4) #改变a子对象值
>>> print(a) # {1: [1, 2, 3, 4]}
>>> print(b) # {1: [1, 2, 3, 4]} # b中子对象的值跟着变了
>>> a[2] = [7, 8] # 改变a外层对象
>>> print(a) # {1: [1, 2, 3, 4], 2: [7, 8]}
>>> print(b) # {1: [1, 2, 3, 4]} # b外层对象不跟着变
三.深拷贝
- 完全拷贝了父对象及其子对象
>>> # a, b内存地址不同,a, b子对象的内存地址也不同
>>> # a, b的变化完全无关
>>> import copy
>>> a = {1: [1, 2, 3]}
>>> b = copy.deepcopy(a)
>>> id(a), id(b) # a, b内存地址不同
(4413393008, 4414925920)
>>> id(a[1]), id(b[1]) # a, b子对象的内存地址也不同
(4414889736, 4414934344)
>>> a[2] = [7, 8] #改变a外层对象, a, b的变化完全无关
>>> print(a) # {1: [1, 2, 3], 2: [7, 8]}
>>> print(b) # {1: [1, 2, 3]}
>>> b[1].append(4)# 改变b内层子对象,a, b的变化完全无关
>>> print(a) # {1: [1, 2, 3], 2: [7, 8]}
>>> print(b) # {1: [1, 2, 3]}
结论
- 深浅拷贝都是对源对象的复制,占用不同的内存空间
- 如果源对象只有一级目录的话,源做任何改动,不影响深浅拷贝对象
- 如果源对象不止一级目录的话,源做任何改动,都要影响浅拷贝,但不影响深拷贝
- 序列对象的切片其实是浅拷贝,即只拷贝顶级的对象