Python中拷贝是有深度的!

六眼飞鱼酱① 提交于 2020-03-04 06:07:02

列表的拷贝

开始学习Python的时候我们应该在很多地方听到或学到这样一个问题,就是s = l[:],s(列表)可以实现l(列表)的拷贝:

l = [1, 3, 6]
s = l[:]
print(s, l is s)

结果为:

[1, 3, 6] False

显而易见,我们得到了l的一个副本,就是l与s只是值相同。我们可以测试下:

s[0] = 99
print(l, s)

结果为:

[1, 3, 6] [99, 3, 6]

就这个例子来说我们实现了拷贝。但是!并不是l[:]就能实现拷贝,这是由Python拷贝的深度决定的,举个例子:

l = [[1, 3, 8], 6, 7]
s = l[:]
print(l is s, l[0] is s[0])

结果:

False True

显然我们实现了l的拷贝,但是却不能将嵌套在l内部的列表一起复制了。个人认为这就是拷贝深度的问题!我们看下带来的问题:

s[0][0] = -99
print(l, s)

嵌套的列表是没有能够被拷贝的,s对嵌套的列表修改其元素都会影响l中的嵌套列表

[[-99, 3, 8], 6, 7] [[-99, 3, 8], 6, 7]

我们拷贝的是嵌套列表的索引,除非我们打破这个索引!

s[0] = None # 这样原先的指向就断了,索引被拷贝的关系就不在了
print(l, s)

这点需要好好理解,拷贝索引和拷贝的深度同样重要!!

[[-99, 3, 8], 6, 7] [None, 6, 7]
  • 总结
  1. python默认浅拷贝,这样拷贝时优先拷贝索引,共用内存,节省空间!
  2. 如果你的目的是一定深度的拷贝,那么这个python自动优化就成了困扰。

实现深度拷贝

假设对于嵌套列表你需要实现完全意义上的拷贝,那么可以这么做:

from copy import deepcopy
l = [[1, 3, 8], 6, 7]
s = deepcopy(l)
s[0][0] = -99
print(l, s)

实现了深度的拷贝:

[[1, 3, 8], 6, 7] [[-99, 3, 8], 6, 7]
  • 我测试了自己3.8版本,list.copy()也能实现深度拷贝。
  • 个人感觉深度拷贝的理解有助于拷贝索引和如何打断索引。
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!