copy()与deepcopy()之间的区分必须要涉及到python对于数据的存储方式。

首先直接上结论:

  • 我们寻常意义的复制就是深复制,即将被复制对象完全再复制一遍作为独立的新个体单独存在。所以改变原有被复制对象不会对已经复制出来的新对象产生影响。
  • 而浅复制并不会产生一个独立的对象单独存在,他只是将原有的数据块打上一个新标签,所以当其中一个标签被改变的时候,数据块就会发生变化,另一个标签也会随之改变。这就和我们寻常意义上的复制有所不同了。

对于简单的 object,用 shallow copy 和 deep copy 没区别

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

看不懂文字没关系我们来看代码:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

>>> import copy

>>> origin = [1,2,[3,4]]

#origin里边有三个元素:1,2,[3,4]

>>> cop1 = copy.copy(origin)

>>> cop2 = copy.deepcopy(origin)

>>> cop1 == cop2

True

>>>cop1 is cop2

False

#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和cop2

可以看到 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 中可能遇到的诡异情况:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

>>> 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 变了

上面两段代码中,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的时候到底发生了什么?

再看一段代码:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

>>> import copy

>>> origin = [1,2,[3,4]]

#origin里边有三个元素:1,2,[3,4]

>>> cop1 = copy.copy(origin)

>>> cop2 = copy.deepcopy(origin)

>>> cop1 == cop2

True

>>> cop1 is cop2

False

#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和cop2

学过docker的人应该对镜像这个概念不陌生,我们可以把镜像的概念套用在copy上面。

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的时候会将复杂对象的每一层复制一个单独的个体出来。

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

来源:https://www.weidianyuedu.com

Python copy()与deepcopy()方法的区别相关推荐

  1. python中函数和方法的区别?Python编程判断当前获取的对象是函数还是方法

    python中函数和方法的区别?Python编程判断当前获取的对象是函数还是方法 目录

  2. python中函数和方法的区别

    本篇内容主要介绍从几个维度来介绍下python中函数和方法的区别: 首先,从分类的角度来分析. (1)函数的分类: 内置函数:python内嵌的一些函数. 匿名函数:一行代码实现一个函数功能. 递归函 ...

  3. Python中copy和deepcopy中的区别

    最近在学习 Python编程,遇到copy和deepcopy感到很困惑,现在针对这两个方法进行区分,一种是浅复制(copy),一种是深度复制(deepcopy). 首先说一下deepcopy,所谓的深 ...

  4. python copy()和deepcopy()解释(import copy)

    对于简单的 object,用 shallow copy 和 deep copy 没区别 复杂的 object, 如 list 中套着 list 的情况,shallow copy 中的 子list,并未 ...

  5. python copy()和deepcopy()解释(浅拷贝、深拷贝)

    对于简单的 object,用 shallow copy 和 deep copy 没区别 复杂的 object, 如 list 中套着 list 的情况,shallow copy 中的 子list,并未 ...

  6. python copy与deepcopy (拷贝与深拷贝)

    copy与deepcopy python 中的copy与deepcopy是内存数据的操作,但是两个函数有一定的区别. 1.copy import copy list = [1, [4, 5, 6], ...

  7. python3下关于copy和deepcopy中的区别

    很多人在学习python3的时候,在字典部分copy和deepcopy感到很困惑,现在针对这两个方法进行区分,即一种是浅复制(copy),一种是深度复制(deepcopy). 开头先下个结论 我们日常 ...

  8. 【Python 必会技巧】copy 模块中 copy() 与 deepcopy() 函数的区别

    Python 中赋值语句不复制对象,而是在目标和对象之间创建绑定关系.对于自身可变或者包含可变项的集合对象,开发者有时会需要生成其副本用于改变操作,进而避免改变原对象.copy 模块提供了通用的浅层复 ...

  9. python:copy()和deepcopy()区别

    1.对象的赋值 都是进行对象引用(内存地址)传递,即'' b is a'' ,a 变 b 也变 2.copy.copy(x):浅拷贝 会创建一个新的对象,即 "b is not a" ...

最新文章

  1. 程序猿才感同身受的10个图!
  2. 如何使用eclipse打开已有工程
  3. webdynpro GOS BDS 文档/附件 上传下载处理
  4. 微服务、容器、DevOps三者之间的演进关系,你清楚吗?
  5. BZOJ-2194 快速傅立叶之二
  6. 培智计算机教学论文,【培智数学论文】_培智数学教学论文
  7. 机器学习必备:前20名Python人工智能和机器学习开源项目
  8. 使用乱序标签来控制HTML的输出效果
  9. linux文件的查看指令-cat-more-less
  10. 智伴机器人广西团队_畅想科技 智绘未来——2020年全区乡村学校少年宫科技体验日活动在广西科技馆举办...
  11. php txt 下载文件,PHP下载单个TXT文件
  12. 【DevOps】软件开发生命周期
  13. win7 升级IE11
  14. 她力量系列七丨兰艳艳:理想温暖10年科研路,女性可以柔和,更要自信、专业 | 妇女节特辑
  15. Linux-引导过程与服务控制
  16. 数据可视化之中国足球队在国际足联及亚洲的历史排名看这儿
  17. uni-app升级思路(前端角度)
  18. python大写数字转阿拉伯数字脚本
  19. 个人计算机中的防毒软件无法防御,win10系统中无法启动defender防御软件的处理办法...
  20. 大数据中的物联网运用

热门文章

  1. ReID:通用性能评价标准
  2. 小程序接入流量主、banner广告、激励广告
  3. C++封装复数类,实现复数运算
  4. 您的captcha验证码设置对了吗?
  5. 了解一下ISO 8601是什么
  6. 坚持每天学习,让学习成为一种习惯
  7. 综合案例----学生管理系统
  8. 记一次亲身经历的高速三车追尾及处理全流程
  9. 去虚拟化 VMware Workstation Pro去虚拟化底层文件修改器
  10. 大数据给保险业带来巨大商业价值