转http://blog.csdn.net/qq_32907349/article/details/52190796

最近在实习,boss给布置了一个

其实呢,copy()与deepcopy()之间的区分必须要涉及到python对于数据的存储方式。首先直接上结论:

—–我们寻常意义的复制就是深复制,即将被复制对象完全再复制一遍作为独立的新个体单独存在。所以改变原有被复制对象不会对已经复制出来的新对象产生影响。

—–而浅复制并不会产生一个独立的对象单独存在,他只是将原有的数据块打上一个新标签,所以当其中一个标签被改变的时候,数据块就会发生变化,另一个标签也会随之改变。这就和我们寻常意义上的复制有所不同了。对于简单的 object,用 shallow copy 和 deep copy 没区别

复杂的 object, 如 list 中套着 list 的情况,shallow copy 中的 子list,并未从原 object 真的「独立」出来。也就是说,如果你改变原 object 的子 list 中的一个元素,你的 copy 就会跟着一起变。这跟我们直觉上对「复制」的理解不同。

看不懂文字没关系我们来看代码:>>>import copy>>>origin = [1, 2, [3, 4]]#origin 里边有三个元素:1, 2,[3, 4]>>>cop1 = copy.copy(origin)>>>cop2 = copy.deepcopy(origin)>>>cop1 == cop2True>>>cop1 is cop2False #cop1 和 cop2 看上去相同,但已不再是同一个object>>>origin[2][0] = "hey!" >>>origin[1, 2, ['hey!', 4]]>>>cop1[1, 2, ['hey!', 4]]>>>cop2[1, 2, [3, 4]]#把origin内的子list [3, 4] 改掉了一个元素,观察 cop1 和 cop21

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

181

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

可以看到 cop1,也就是 shallow copy 跟着 origin 改变了。而 cop2 ,也就是 deep copy 并没有变。

似乎 deep copy 更加符合我们对「复制」的直觉定义: 一旦复制出来了,就应该是独立的了。如果我们想要的是一个字面意义的「copy」,那就直接用 deep_copy 即可。

那么为什么会有 shallow copy 这样的「假」 copy 存在呢? 这就是有意思的地方了。python的数据存储方式

Python 存储变量的方法跟其他 OOP 语言不同。它与其说是把值赋给变量,不如说是给变量建立了一个到具体值的 reference。

当在 Python 中 a = something 应该理解为给 something 贴上了一个标签 a。当再赋值给 a 的时候,就好象把 a 这个标签从原来的 something 上拿下来,贴到其他对象上,建立新的 reference。 这就解释了一些 Python 中可能遇到的诡异情况:>> a = [1, 2, 3]>>> b = a>>> a = [4, 5, 6] //赋新的值给 a>>> a[4, 5, 6]>>> b[1, 2, 3]# a 的值改变后,b 并没有随着 a 变>>> a = [1, 2, 3]>>> b = a>>> a[0], a[1], a[2] = 4, 5, 6 //改变原来 list 中的元素>>> a[4, 5, 6]>>> b[4, 5, 6]# a 的值改变后,b 随着 a 变了1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

171

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

上面两段代码中,a 的值都发生了变化。区别在于,第一段代码中是直接赋给了 a 新的值(从 [1, 2, 3] 变为 [4, 5, 6]);而第二段则是把 list 中每个元素分别改变。

而对 b 的影响则是不同的,一个没有让 b 的值发生改变,另一个变了。怎么用上边的道理来解释这个诡异的不同呢?

首次把 [1, 2, 3] 看成一个物品。a = [1, 2, 3] 就相当于给这个物品上贴上 a 这个标签。而 b = a 就是给这个物品又贴上了一个 b 的标签。

第一种情况:

a = [4, 5, 6] 就相当于把 a 标签从 [1 ,2, 3] 上撕下来,贴到了 [4, 5, 6] 上。

在这个过程中,[1, 2, 3] 这个物品并没有消失。 b 自始至终都好好的贴在 [1, 2, 3] 上,既然这个 reference 也没有改变过。 b 的值自然不变。

第二种情况:

a[0], a[1], a[2] = 4, 5, 6 则是直接改变了 [1, 2, 3] 这个物品本身。把它内部的每一部分都重新改装了一下。内部改装完毕后,[1, 2, 3] 本身变成了 [4, 5, 6]。

而在此过程当中,a 和 b 都没有动,他们还贴在那个物品上。因此自然 a b 的值都变成了 [4, 5, 6]。

搞明白这个之后就要问了,对于一个复杂对象的浅copy,在copy的时候到底发生了什么?

再看一段代码:>>>import copy>>>origin = [1, 2, [3, 4]]#origin 里边有三个元素:1, 2,[3, 4]>>>cop1 = copy.copy(origin)>>>cop2 = copy.deepcopy(origin)>>>cop1 == cop2True>>>cop1 is cop2False #cop1 和 cop2 看上去相同,但已不再是同一个object>>>origin[2][0] = "hey!" >>>origin[1, 2, ['hey!', 4]]>>>cop1[1, 2, ['hey!', 4]]>>>cop2[1, 2, [3, 4]]#把origin内的子list [3, 4] 改掉了一个元素,观察 cop1 和 cop21

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

181

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

学过

概念图如下:

copy对于一个复杂对象的子对象并不会完全复制,什么是复杂对象的子对象呢?就比如序列里的嵌套序列,字典里的嵌套序列等都是复杂对象的子对象。对于子对象,python会把它当作一个公共镜像存储起来,所有对他的复制都被当成一个引用,所以说当其中一个引用将镜像改变了之后另一个引用使用镜像的时候镜像已经被改变了。

所以说看这里的origin[2],也就是 [3, 4] 这个 list。根据 shallow copy 的定义,在 cop1[2] 指向的是同一个 list [3, 4]。那么,如果这里我们改变了这个 list,就会导致 origin 和 cop1 同时改变。这就是为什么上边 origin[2][0] = “hey!” 之后,cop1 也随之变成了 [1, 2, [‘hey!’, 4]]。

而deepcopy概念图如下:

deepcopy的时候会将复杂对象的每一层复制一个单独的个体出来。

这时候的 origin[2] 和 cop2[2] 虽然值都等于 [3, 4],但已经不是同一个 list了。即我们寻常意义上的复制。

python中copy是什么意思_Python-copy()与deepcopy()区别相关推荐

  1. [转载] python中for语句用法_详解Python中for循环的使用_python

    参考链接: 在Python中将else条件语句与for循环一起使用 这篇文章主要介绍了Python中for循环的使用,来自于IBM官方网站技术文档,需要的朋友可以参考下 for 循环 本系列前面 &q ...

  2. python中for语句用法_详解Python中for循环的使用_python

    这篇文章主要介绍了Python中for循环的使用,来自于IBM官方网站技术文档,需要的朋友可以参考下 for 循环 本系列前面 "探索 Python,第 5 部分:用 Python 编程&q ...

  3. python中异或怎么算_python 异或运算的前提_异或运算公式

    Python基础(10)–数字-Python-第七城市 609x288 - 73KB - JPEG Python基础(10)--数字_资讯_突袭网 609x288 - 33KB - JPEG pyth ...

  4. python中模块是什么意思_Python中的模块是什么?3分钟搞懂Python中的模块问题

    Python 中的模块是一个 Python 文件,以 .py 结尾,包含了 Python 对象定义和Python语句,模块让你能够有逻辑地组织你的 Python 代码段.把相关的代码分配到一个模块里能 ...

  5. python的re2和re区别_浅谈Python中re.match()和re.search()的使用及区别

    1.re.match()fvk免费资源网 re.match()的概念是从头匹配一个符合规则的字符串,从起始位置开始匹配,匹配成功返回一个对象,未匹配成功返回None.fvk免费资源网 包含的参数如下: ...

  6. python中str函数isdigit、isdecimal、isnumeric的区别

    python中str函数isdigit.isdecimal.isnumeric的区别 num = "1"  #unicode num.isdigit()   # True num. ...

  7. 【整理】Python中的re.search和re.findall之间的区别和联系 + re.finall中带命名的组,不带命名的组,非捕获的组,没有分组四种类型之间的区别

    之前自己曾被搞晕过很多次. 后来使用这些函数次数多了之后,终于比较清楚的弄懂了两者之间的区别和关系了. 尤其是一些细节方面的注意事项了. 在看下面的总结和代码之前,请先确保你对如下基本概念已经有所了解 ...

  8. python中items()和iteritems()的区别

    python中items()和iteritems()的区别 一.两个函数的作用 字典的items方法作用:是可以将字典中的所有项,以列表方式返回.因为字典是无序的,所以用items方法返回字典的所有项 ...

  9. python的input添加变量_在python中如何定义一个全局变量raw_input() 与 input()的区别...

    raw_input和input两个均是 python 的内建函数,通过读取控制台的输入与用户实现交互.但他们的功能不尽相同.下面举两个例子,来说明两者使用上的不同. 例子1Python 2.7.5 ( ...

  10. python中的方法需要定义_Python中规范定义命名空间的一些建议

    API的设计是一个艺术活.往往需要其简单.易懂.整洁.不累赘. 很多时候,我们在底层封装一个方法给高层用,而其它的方法只是为了辅助这个方法的. 也就是说我们只需要暴露这个方法就行,不用关心这个方法是怎 ...

最新文章

  1. Intel GPU实现游戏与数据中心
  2. 高德地图SDK大致使用
  3. mac搭建appium自动化之testNG
  4. Use Asynchronous Apex
  5. Dynamics CRM 2015/2016 Web API:Unbound Custom Action 和 Bound Custom Action
  6. appium学习链接记录
  7. 关于Fragment 不响应onActivityResult的情况分析
  8. golangd历史版本下载路径
  9. Java面向对象编程三大特征 - 继承
  10. alc236黑苹果驱动_瑞昱 Realtek2.5G有线网卡 | RTL8125、RTL8156黑苹果驱动
  11. 计算机屏幕显示不全怎么办,电脑打开软件后屏幕显示不全怎么办
  12. Office Professional Plus 2010 产品密钥
  13. postgresql中sql查询语句报错处理——ERROR: failed to find conversion function from unknown to text
  14. 爬取阿里云物联网平台设备的物模型数据
  15. zabbix系列(十) 监控内存可用率
  16. Python: queue.Queue
  17. 登录超时提示+踢人下线实现(spring security)
  18. srg2220_华为SRG2200路由器系列配置说明
  19. java三元表达式必须返回_java – 三元运算符的右手表达式必须兼容...
  20. 线性代数方程组数值解法

热门文章

  1. Vite 搭建 Vue2 项目(Vue2 + vue-router + vuex)
  2. 从400多k的大小减到了2B,我的APP是怎么优化的?
  3. Spring学习理解---后置处理器
  4. 【翻译】西川善司为了3D游戏粉丝的[生化危机5]图形讲座(后篇)
  5. mysql模糊查询限制范围_MySql 模糊查询、范围查询
  6. 赚钱发财必备七大能力
  7. 【第141期】游戏策划:清华大学游戏制作人/策划研究生,开课了
  8. ubuntu18.04连接蓝牙耳机
  9. latex tikz使用总结
  10. ant-design for vue. table合并单元格通用方法