在Python编程中忽略深拷贝和浅拷贝可能会造成未知的风险。
  比如我们打算保存一份原始对象的副本作为上一状态的记录,此后修改原始对象数据时,若是副本对象的数据也发生改变,那么这就是一个严重的错误。
  注:这里我们称被拷贝的对象为原始对象,拷贝生成的副本称为副本对象
 
  下面我们看个例子:
# :假设cuboid中保存了两个长方体的长、宽、高。
>>> cuboid= [[1, 2, 3], [2, 3, 4]]
# :有多种方式生成cuboid的副本,这里使用list()方法。
>>> cuboid_tmp = list(cuboid)
>>> cuboid_tmp
[[1, 2, 3], [2, 3, 4]]
# :修改原始对象数据。
>>> cuboid[0][1] = 10
>>> cuboid
[[1, 10, 3], [2, 3, 4]]
# :查看副本对象中数据并与原始对象数据对比。
>>> cuboid_tmp
[[1, 10, 3], [2, 3, 4]]
  上面例子中,副本对象中数据被原始对象中数据影响了,此时我们怀疑原始对象和副本对象是不是引用地址相同?
  我们看一下这两个对象的地址。
>>> id(cuboid)
2827786472008
>>> id(cuboid_tmp)
2827786472200 # 不一样
  结果证明,并不是,其实list()方法就是一种浅拷贝方式,只有深入理解深拷贝和浅拷贝才能防止此种错误的发生。
 
  下面是我整理的深浅拷贝和赋值的知识点。(虽然赋值操作不是拷贝,但是这里也有必要说一下。)

浅拷贝

  一句话来概括浅拷贝就是,原始对象和副本对象还是藕断丝连。
  浅拷贝对于要拷贝的数据是否是复合数据,表现又不同。
  我们看下面非复合数据的例子。
# :假设cuboid中保存了一个长方体的长、宽、高。
>>> cuboid= [1, 2, 3]
# :我们还是使用list()浅拷贝生成一个副本。
>>> cuboid_tmp = list(cuboid)
# :修改原始对象数据。
>>> cuboid[1] = 10
>>> cuboid
[1, 10, 3]
# :查看副本对象中数据并与原始对象数据对比。
>>> cuboid_tmp
[1, 2, 3]
  咦!不是说list()是浅拷贝吗?为什么此时副本对象的数据没有发生更改呢。
  不急,我们再看一下原始对象和副本对象的地址。
>>> id(cuboid)
2827786471176
>>> id(cuboid_tmp)
2827786484936 # 不一样
  我们再来看看原始对象和副本对象中每个数据的地址。
>>> for i in cuboid:
... print(id(i))
140733841519440
140733841519728
140733841519504
>>>
>>> for i in cuboid_tmp:
... print(id(i))
140733841519440 # 一样
140733841519472 # 不一样
140733841519504 # 一样
  我们发现除了修改后的第二个元素地址不一样外,其它元素地址是相同的。
  这些说明了浅拷贝后,原始对象和副本对象中元素引用指向相同的地址。
  当修改原始对象中某个元素的值时,其对应元素的引用地址发生了改变,但是副本对象中不会受到影响,所以才产生了上面的结果。
  下面我们通过图更加深刻的理解非复合数据浅拷贝后原始对象和副本对象的关系。

  回到文章最开头的例子,同样是浅拷贝,为什么复合数据的浅拷贝,修改原始数据,可能对副本数据造成影响。(这里用的可能,因为修改原始对象不一定就会修改副本对象)
  我们再来通过绘图分析。

  浅拷贝只是拷贝第一层元素对象(子列表),即原始对象和副本对象中元素都是指向相同的子列表,子列表中数据元素发生变化不影响子列表的索引位置。
  针对浅拷贝,我们完全可以将复合数据抽象成非复合数据去思考,然后参考非复合数据的增删改来思考原始对象和副本对象是否会互相影响。
深拷贝
  深拷贝更好理解,我们只需要知道原始对象和副本对象完全不相关,不会互相影响就行。
赋值 
  我们经常会在编程过程中使用赋值操作,赋值操作类似于windows中创建快捷方式,原始引用和副本引用指向同一个地址。
>>> cuboid = [1,2,3]
>>> cuboid_tmp = cuboid
>>> id(cuboid)
1919680744520
>>> id(cuboid_tmp)
1919680744520 # 一样
  所以说当我们改变原始引用中数据时,副本引用指向的数据也会发生改变,因为两个引用指向的同一个地址。
>>> cuboid[1] = 10
>>> cuboid
[1, 10, 3]
>>> cuboid_tmp
[1, 10, 3]

001 说说Python中的深拷贝和浅拷贝的更多相关文章

  1. **Python中的深拷贝和浅拷贝详解

    Python中的深拷贝和浅拷贝详解   这篇文章主要介绍了Python中的深拷贝和浅拷贝详解,本文讲解了变量-对象-引用.可变对象-不可变对象.拷贝等内容.   要说清楚Python中的深浅拷贝,需要 ...

  2. python中的深拷贝与浅拷贝

    深拷贝和浅拷贝 浅拷贝的时候,修改原来的对象,浅拷贝的对象不会发生改变. 1.对象的赋值 对象的赋值实际上是对象之间的引用:当创建一个对象,然后将这个对象赋值给另外一个变量的时候,python并没有拷 ...

  3. python中的深拷贝和浅拷贝理解

    在python中,对象赋值实际上是对象的引用.当创建一个对象,然后把它赋给另一个变量的时候,python并没有拷贝这个对象,而只是拷贝了这个对象的引用.以下分两个思路来分别理解浅拷贝和深拷贝: 利用切 ...

  4. python中的深拷贝和浅拷贝

    python的复制,深拷贝和浅拷贝的区别   在python中,对象赋值实际上是对象的引用.当创建一个对象,然后把它赋给另一个变量的时候,python并没有拷贝这个对象,而只是拷贝了这个对象的引用 一 ...

  5. Python 中的深拷贝和浅拷贝

    一.浅拷贝python中 对象赋值时 默认是浅拷贝,满足如下规律:1. 对于 不可变对象(字符串,元组 等),赋值 实际上是创建一个新的对象:例如: >>> person=['nam ...

  6. python中的深拷贝和浅拷贝(面试题二)

    一.浅拷贝 定义:浅拷贝只是对另外一个变量的内存地址的拷贝,这两个变量指向同一个内存地址的变量值. 浅拷贝的特点: 公用一个值: 这两个变量的内存地址一样: 对其中一个变量的值改变,另外一个变量的值也 ...

  7. python中的深拷贝和浅拷贝(面试题)

    一.浅拷贝 定义:浅拷贝只是对另外一个变量的内存地址的拷贝,这两个变量指向同一个内存地址的变量值. 浅拷贝的特点: 公用一个值: 这两个变量的内存地址一样: 对其中一个变量的值改变,另外一个变量的值也 ...

  8. 【转】Python中的赋值、浅拷贝、深拷贝介绍

    这篇文章主要介绍了Python中的赋值.浅拷贝.深拷贝介绍,Python中也分为简单赋值.浅拷贝.深拷贝这几种"拷贝"方式,需要的朋友可以参考下   和很多语言一样,Python中 ...

  9. 浅谈Java中的深拷贝和浅拷贝(转载)

    浅谈Java中的深拷贝和浅拷贝(转载) 原文链接: http://blog.csdn.net/tounaobun/article/details/8491392 假如说你想复制一个简单变量.很简单: ...

随机推荐

  1. The 2019 ICPC Asia Shanghai Regional Contest H Tree Partition k、Color Graph

    H题意: 给你一个n个节点n-1条无向边构成的树,每一个节点有一个权值wi,你需要把这棵树划分成k个子树,每一个子树的权值是这棵子树上所有节点权值之和. 你要输出这k棵子树的权值中那个最大的.你需要让 ...

  2. trie浅谈

    关于trie ​ 其实字典树和以上两种算法有很大不同,但是hash由于其优秀的应用,导致有些字符串查找用hash也是可行的. ​ 字典树中支持添加,查找,区间查询(可持久化字典树),而且在异或操作上有 ...

  3. AtCoder Beginner Contest 172

    比赛链接:https://atcoder.jp/contests/abc172/tasks A - Calc 题意 给出一个正整数 $a$,计算 $a + a^2 + a^3$ .($1 \le a ...

  4. R - 0 or 1(最短路)

    Given a n*n matrix C ij (1<=i,j<=n),We want to find a n*n matrix X ij (1<=i,j<=n),which ...

  5. Codeforces Round #660 (Div. 2) C. Uncle Bogdan and Country Happiness (DFS)

    题意:有\(n\)个人,每个人居住在某个节点,所有人都在节点\(1\)上班,下班后沿着最短路径回家,在回家途中心情可能会变差(心情只会变差不会变好),每个节点都有一个开心值,开心值等于所有经过时的好心 ...

  6. Databricks 第11篇:Spark SQL 查询(行转列、列转行、Lateral View、排序)

    本文分享在Azure Databricks中如何实现行转列和列转行. 一,行转列 在分组中,把每个分组中的某一列的数据连接在一起: collect_list:把一个分组中的列合成为数组,数据不去重,格 ...

  7. Ansible 自动化部署

    参考 BLOG: Ansible 系列模块 Ansible 部署与使用 Ansible Book Ansible Ansible 是一个自动化统一配置管理工具,自动化主要体现在 Ansible 集成了 ...

  8. Java RMI 实现一个简单的GFS(谷歌文件系统)——背景与设计篇

    目录 背景 系统设计 1. 系统功能 2. Master组件 2.1 命名空间 2.2 心跳机制 2.3 故障恢复和容错机制 3. ChunkServer组件 3.1 本地存储 3.2 内存命中机制 ...

  9. javascript questions & code review

    javascript questions & code review refs https://github.com/learning-js-by-reading-source-codes/j ...

  10. no code form generator

    no code form generator 无代码,表单生成器 H5 Drag & Drop UI => codes click copy demo https://www.forms ...