深浅copy,何为深浅copy,深copy和浅copy两者有何不同
copy,拷贝,顾名思义,自然是把东西复制过来,呈现在眼前的是一样的,例如:
a = [1,2,3,4,5] b = a b.append(6) print(a,b)
输出:
[1, 2, 3, 4, 5, 6] [1, 2, 3, 4, 5, 6]
很明显,a和b的值是一样的。因为对于赋值运算来讲,a与b指向的是同一内存地址,所以他们完全是一样的
浅copy:
a = [1,2,3,4,[5]] b = copy.copy(a) b[4].append(6) print(a) print(b) print(id(a)) print(id(b)) print(id(a[0])) print(id(b[0])) print(id(a[4])) print(id(b[4]))
输出:
[1, 2, 3, 4, [5, 6]] [1, 2, 3, 4, [5, 6]] 3123924048968 3123924049032 140709039403264 140709039403264 3123924285128 3123924285128
可以看到,a和b的输出地址不一样,原因是对于浅copy来说,只是在内存中重新创建了开辟了一个空间存放一个新列表,但是新列表中的元素与原列表中的元素是公用的,且元素原地址一样不变。
但我们如果对它进行增删改,两者是否会相互改变呢?
从上面看,列表当中的可变数据类型进行增加元素时,两者是会相互影响的,且地址一直一致;
但从下面看,对列表当中的不可变数据类型进行修改时,虽然元素地址一样,但两者是不会相互影响,并且经过修改后,元素地址发生改变,两者地址变得不一样。
import copy a = [1,2,3,4,[5]] b = copy.copy(a) b[0] = 0
print(a)
print(b)
print(id(a[0])) print(id(b[0]))
输出:
[1, 2, 3, 4, [5]] [0, 2, 3, 4, [5]] 140709362168064 140709362168032
而在整个列表添加新的元素时,两者同样不会相互影响,只要copy过来的元素不发生改变,元素地址会一直保持一致
import copy a = [1,2,3,4,[5]] b = copy.copy(a) b.append(8) print(a) print(b) print(id(a[0])) print(id(b[0]))
输出:
[1, 2, 3, 4, [5]] [1, 2, 3, 4, [5], 8] 140709362168064 140709362168064
所以得出结论是,浅copy时,内存会开辟一个新的空间存放一个新的列表,所以地址不一致。列表中的元素和元素地址都会被copy过来,而可变数据类型(列表中的列表,二级列表)被当作一个整体不被拷贝,所以地址永远一致,对可变数据类型中的元素改变时,a和b会相互影响,元素永远相同。
而一级列表中的不可变数据类型,虽然元素与地址都被复制过来,但两者进行修改时不会相互影响,并且修改后地址会变得不一致。而在一级列表添加新的元素时,两者同样不会相互影响,只要不改变copy过来的元素,地址会一直与copy过来的一致。
深copy:
import copy a = [1,2,3,4,[5]] b = copy.deepcopy(a) b[4].append(6) print(a) print(b) print(id(a)) print(id(b)) print(id(a[0])) print(id(b[0])) print(id(a[4])) print(id(b[4]))
输出:
[1, 2, 3, 4, [5]] [1, 2, 3, 4, [5, 6]] 1861657304264 1861657304328 140709043532032 140709043532032 1861657540168 1861657304456
它是拷贝所有内容。包括内部(列表的列表)的所有,形成一个新的对象,虽然与之前的值和内容一模一样,但是它们时完完全全的两个对象,所以不仅a和b的地址不同,可变数据类型的地址同样被拿出来存在新的内存当中,地址同样会不一样,所以做出改变时不会相互影响;其它与浅copy一致,不可变数据类型改变时不会相互影响,且改变后地址会发生改变;
注:
当切片进行赋值时,两者地址会不一样,并且进行增删改时,两者互不影响:
a = [1,2,3,4,5] b = a[0::] b.pop(0) print(a) print(b) print(id(a)) print(id(b))
输出:
[1, 2, 3, 4, 5] [2, 3, 4, 5] 2525473650376 2525473414152
仅存在一种情况,两者相互影响且地址永远一致:
a = [1,2,3,4,5] b = a b.append(6) a.pop(2) print(a) print(b) print(id(a)) print(id(b))
输出:
[1, 2, 4, 5, 6] [1, 2, 4, 5, 6] 2957431125704 2957431125704
以上测试基于python3.7.4