在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. 2019牛客暑期多校训练营(第七场)H.Pair(数位dp)

    题意:给你三个数A,B,C 现在要你找到满足  A and B >C 或者 A 异或 B < C 的对数. 思路:我们可以走对立面 把既满足 A and B <= C 也满足 A 异 ...

  2. Codeforces Round #678 (Div. 2)【ABCD】

    比赛链接:https://codeforces.com/contest/1436 A. Reorder 题解 模拟一下这个二重循环发现每个位置数最终都只加了一次. 代码 #include <bi ...

  3. HDU6311 Cover【欧拉路径 | 回路】

    HDU6311 Cover 题意: 给出\(N\)个点的简单无向图,不一定联通,现在要用最少的路径去覆盖所有边,并且每条边只被覆盖一次,问最少路径覆盖数和各条路径 \(N\le 10^5\) 题解: ...

  4. hdu4028 The time of a day (map+dp)

    Problem Description There are no days and nights on byte island, so the residents here can hardly de ...

  5. Codeforces Educational Rounds 85 A~C

    A:Level Statistics 题意:统计n个游戏数据,p代表游玩次数,c代表通关次数,每次游玩都不一定通关,求这些数据是否合法 题解:1.游玩次数不能小于通关次数   2.游玩次数和通关次数必 ...

  6. CQRS+Event Sourcing

    using System; using System.Collections.Generic; using System.Linq; namespace CQRS { public class Eve ...

  7. 6.PowerShell DSC核心概念之LCM

    什么是LCM? 本地配置管理器 (LCM) 是DSC的引擎. LCM 在每个目标节点上运行,负责分析和执行发送到节点的配置. 它还负责 DSC 的许多方面,包括以下各方面. 确定刷新模式(推送或请求) ...

  8. Linux程序设计——Linux基础

    1. 什么是Linux 1)Linux系统是一种自由和开放源代码的类UNIX的完整操作系统. 2)林纳斯·本纳第克特·托瓦兹(LinusBenedictTorvalds,1969年~) 3)诞生于19 ...

  9. 数位dp【模板 + 老年康复】

    学习博客: 戳这里 戳这里 "在信息学竞赛中,有这样一类问题:求给定区间中,满足给定条件的某个D 进制数或此类数的数量.所求的限定条件往往与数位有关,例如数位之和.指定数码个数.数的大小顺序 ...

  10. JVM 报 GC Overhead limit exceeded 是什么意思?

    默认情况下,并不是等堆内存耗尽,才会报 OutOfMemoryError,而是如果 JVM 觉得 GC 效率不高,也会报这个错误. 那么怎么评价 GC 效率不高呢?来看下源码: 呢?来看下源码gcOv ...