码迷,mamicode.com
首页 > 其他好文 > 详细

深浅copy,何为深浅copy,深copy和浅copy两者有何不同

时间:2019-08-12 23:47:35      阅读:128      评论:0      收藏:0      [点我收藏+]

标签:app   内存地址   基于   div   class   python   内存   赋值运算   pytho   

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

 

深浅copy,何为深浅copy,深copy和浅copy两者有何不同

标签:app   内存地址   基于   div   class   python   内存   赋值运算   pytho   

原文地址:https://www.cnblogs.com/aizhinong/p/11336879.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!