今天在写一个小程序的时候用到了2维数组, 顺手就写成了[[0.0]*length]*length, 结果为了这个小错,调试了半个多小时,

其实之前对与浅复制和深复制已经做过学习和总结, 但真正编程用到这些知识时还是掉入了陷阱中. 所以在此做进一步的总结:

  本文通过几个实例来说明Python中list的深复制和浅复制:

>>> a = [[]] * 10
>>> a
[[], [], [], [], [], [], [], [], [], []]
>>> a[0][0] = 10    #NO WAY
Traceback (most recent call last):File "<stdin>", line 1, in <module>
IndexError: list assignment index out of range
>>> a[0].append(1)
>>> a
[[1], [1], [1], [1], [1], [1], [1], [1], [1], [1]]

  a[0].append(1)后, 如果a的输出结果让你感到有些困惑,你可以参考这里(原因是Python中的*运算采用的是浅复制).

  同样的道理,下面的代码我们应该都能够理解:

>>> a[3].append(9)
>>> a
[[1, 9], [1, 9], [1, 9], [1, 9], [1, 9], [1, 9], [1, 9], [1, 9], [1, 9], [1, 9]]
>>> a[2][1] = 3
>>> a
[[1, 3], [1, 3], [1, 3], [1, 3], [1, 3], [1, 3], [1, 3], [1, 3], [1, 3], [1, 3]]

  让我们一起来分析一下:

  对于a(理解为一个2维数组)中的每一个元素都是一个list(理解为一个1维数组), 但我们需要注意的是a的每一个元素

a[0],a[1],a[2]...指向的是同一段内存区域(浅复制),所以更改(修改值或添加值)任何一个元素(a[0]或a[1]...a[9])都会直接影

响到其它的元素.

  如何验证a中的每一个元素a[0], a[1],...,a[9]指向同一段内存区域? 可以通过id方法来验证:

>>> id.__doc__
"id(object) -> integer

Return the identity of an object.  This is guaranteed to be unique amongsimultaneously existing objects.  (Hint: it's the object's memory address.)"

>>> a = [[]]*10
>>> a
[[], [], [], [], [], [], [], [], [], []]
>>> id(a[0])
3071938316L
>>> id(a[1])
3071938316L
>>> a[0].append(1)
>>> a
[[1], [1], [1], [1], [1], [1], [1], [1], [1], [1]]
>>> id(a[0])
3071938316L
>>> id(a[1])
3071938316L
>>> 

注意:虽然a的每一个元素a[0],a[1],a[2]...指向的是同一段内存区域,但a中的各个元素是独立的元素(他们相同但不同一),

也就是说删除掉任何一个数据对其他的数据没有任何影响:

>>> a = [[]] * 10
>>> a
[[], [], [], [], [], [], [], [], [], []]
>>> a[0].append(1)
>>> a
[[1], [1], [1], [1], [1], [1], [1], [1], [1], [1]]
>>> len(a)
10
>>> del(a[2])
>>> a
[[1], [1], [1], [1], [1], [1], [1], [1], [1]]
>>> len(a)
9

  那么应该怎么实现深复制呢?其实在前面提到的文章中已经介绍了这一方法:  

>>> c = [[] for i in range(10)]
>>> c
[[], [], [], [], [], [], [], [], [], []]
>>> c[0].append(3)
>>> c
[[3], [], [], [], [], [], [], [], [], []]
>>> 

  至此, 我觉得还有一点需要说明:

  一定要理解*操作的对象是谁, 例如: [2]*10得到[2, 2, 2, 2, 2, 2, 2, 2, 2, 2], *10操作的对象是[]中的2, 也就是说*10操

作使list中的元素2复制10次. 同理[[]]*10得到[[], [], [], [], [], [], [], [], [], []],*10操作的对象是[]中的[], 也就是说*10

操作使list中的元素[]浅复制10次, 这10个空list指向内存中相同的区域(参见上面用id验证部分).

  下面用2段代码作为对比列出来, 便于查看:

>>> a = [2] * 10
>>> a
[2, 2, 2, 2, 2, 2, 2, 2, 2, 2]
>>> id(a[0])
164067492
>>> id(a[1])
164067492
>>> a[0] = 1  #NOTE
>>> id(a[0])  #NOTE
164067504
>>> id(a[1])
164067492
>>> 

>>> b = [[]] * 10
>>> b
[[], [], [], [], [], [], [], [], [], []]
>>> id(b[0])
3072965964L
>>> id(b[1])
3072965964L
>>> b[0].append(10)
>>> id(b[0])
3072965964L
>>> id(b[1])
3072965964L
>>> b
[[10], [10], [10], [10], [10], [10], [10], [10], [10], [10]]
>>> b[0][0] = 1
>>> b
[[1], [1], [1], [1], [1], [1], [1], [1], [1], [1]]
>>> id(b[0])
3072965964L
>>> id(b[1])
3072965964L
>>> b[0] = [10]
>>> b
[[10], [1], [1], [1], [1], [1], [1], [1], [1], [1]]
>>> id(b[1])
3072965964L
>>> id(b[0])
3072965996L
>>> 

转载于:https://www.cnblogs.com/lxw0109/p/shallow-copy-and-deep-copy.html

Shallow Copy Deep Copy in Python list相关推荐

  1. python(numpy,pandas5)——numpy中copy 和 deep copy

    文章目录 前言 copy deep copy 前言 根据 莫烦Python的教程 总结写成,以便自己复习和使用,这里我就不哟林地挂原创了

  2. Python中的浅复制(shallow copy)和深复制(deep copy)

    文章目录 python值管理方式 深复制与浅复制的使用及区别 近期杂事太多,博客一直没更新,9月最后一天了,总得写点吧 今天记一下以前碰到过,最近又碰到的问题:python的深复制和浅复制 神奇的py ...

  3. .NET深入学习笔记(4):深拷贝与浅拷贝(Deep Copy and Shallow Copy)

    今天继续利用准备WSE安全开发文章的空闲时间,完善<.NET深入学习笔记>系列(基本都是.Net重要的知识点,我都做了详细的总结,是什么.为什么.和怎么实现).想必很多人也接触过这两个概念 ...

  4. 浅拷贝(shallow copy)和深拷贝(deep copy)

    浅拷贝(shallow copy):只负责克隆按值传递的数据(比如基本数据类型.String类型) 深拷贝(deep copy):除了shallow copy的值外,还负责克隆引用类型的数据,基本是就 ...

  5. [JAVA]deep copy链表

    deep copy的意思我觉得就是复制一个对象成为新的对象,和原来的对象有不同的内存地址,不是简单的引用复制. 题目来源:leetcode 题目描述: Copy List with Random Po ...

  6. [PYTHON] 深度解析copy.copy() 与 copy.deepcopy()

    在列表中,想要复制一个列表,可以使用copy()函数,在列表中,copy()函数与切片 [:] 功能相同 a=[0,1,[0,1]] b=a.copy() c=a[:] -----print b,c- ...

  7. NumPy学习(索引和切片,合并,分割,copy与deep copy)

    NumPy学习(索引和切片,合并,分割,copy与deep copy) 目录 索引和切片合并分割 copy与deep copy 索引和切片 通过索引和切片可以访问以及修改数组元素的值 一维数组 程序示 ...

  8. Python深度学习:基于PyTorch [Deep Learning with Python and PyTorch]

    作者:吴茂贵,郁明敏,杨本法,李涛,张粤磊 著 出版社:机械工业出版社 品牌:机工出版 出版时间:2019-11-01 Python深度学习:基于PyTorch [Deep Learning with ...

  9. Keras Tutorial: Deep Learning in Python

    This Keras tutorial introduces you to deep learning in Python: learn to preprocess your data, model, ...

最新文章

  1. vue key重复_得心应用的Vue高级技巧
  2. 面试官:说说 Java 中的 Unsafe 和 CAS
  3. Windows保护模式学习笔记(四)—— 中断门陷阱门
  4. java 响应 请求参数_spring基础----请求与响应的参数(一)
  5. MySQL子查询嵌套查询
  6. 【Clion-Ubuntu-dlib】运行一个dlib案例(一)(如何在clion编译器中配置CMakeLists)
  7. P3834 【模板】可持久化线段树 2(整体二分做法)
  8. 44response对象
  9. python应声虫代码_前端大牛们都学过哪些东西?
  10. PostMan 四种常见的 POST 提交数据方式
  11. 为EF DbContext生成的实体添加注释(T5模板应用)[转]
  12. 结合 Apache Kafka 生态系统,谈谈2018年机器学习五大趋势
  13. 跟随进度而变色进度条效果ios源码
  14. 力扣904,水果成篮(JavaScript)
  15. Nginx配置静态资源
  16. 乐优商城(14)–订单服务
  17. ddr4 dqs 频率_ddr4
  18. 【收集】网络上各路大侠放出的面试题、求职技巧
  19. 常见通信协议与通讯协议梳理- 通讯协议
  20. 失传万年的PS致富经典(一)

热门文章

  1. VB2005.Net 环境下使用Jmail组件发送邮件
  2. [react] React中怎么操作虚拟DOM的Class属性
  3. 前端学习(3216):总结state
  4. 前端学习(3197):jsx语法规则1
  5. 前端学习(2159):vuecli脚手架的配置和安装
  6. oracle之单行函数之分组函数
  7. 前端学习(1387):多人管理项目7登录 数据库连接
  8. 前端学习(764):创建对象的三种方式
  9. 第一百二十四期:2019年臭名昭著的勒索软件,网络钓鱼和僵尸网络
  10. QT tr与Qstring的差别