在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. CentOS环境下搭建青岛大学OJ

    1.安装必要的依赖sudo yum updatesudo yum -y install epel-releasesudo yum -y install python-pipsudo yum clean ...

  2. Codeforces 1364C - Ehab and Prefix MEXs

    题意:给1e5的数组a 保证 ai <= ai+1  ai<=i  求一个一样长的数组b 使得mex(b1,b2···bi) = ai QAQ:不知道为啥这1600分的题比赛时出不了 啊啊 ...

  3. Educational Codeforces Round 83 D. Count the Arrays(组合,逆元,快速幂)

    题意: 从 m 个数中选 n - 1 个数组成先增后减的长为 n 的数组. 思路: 因为 n 个数中有两个数相同,所以每种情况实际上只有 n - 1 个不同的数--$c_m^{n - 1}$, 除去最 ...

  4. HDU5732 Subway【树重心 树哈希】

    HDU5732 Subway 题意: 给出两棵大小为\(N\)的同构树,要求输出对应的节点 \(N\le 10^5\) 题解: 由于重心最多只有两个,找到重心之后以重心为根进行树哈希,找到相同哈希值的 ...

  5. hdu5391 Zball in Tina Town

    Problem Description Tina Town is a friendly place. People there care about each other. Tina has a ba ...

  6. C# 通过Internet搜索网络资源

    Internet 网络资源非常丰富,几乎涉及到日常生活和研究的各个方面.流行的搜索引擎像Google.百度.雅虎等都能完成快速搜索网络资源的功能.本节我们将学习用C#实现这些功能的基本思路. 在Sys ...

  7. Docker配置文件deamon.json详解

    vim /etc/docker/daemon.json { "authorization-plugins": [], "data-root": "&q ...

  8. DQL 数据查询语言

    查询数据(SELECT) # 查询所有数据 - 很危险,数据量过大,容易导致内存溢出而宕机 mysql> select * from student; # 先查询数据总量,然后决定是否可以查询所 ...

  9. C++中函数的形式参数引用

    形式参数的传递方式 值传递 值传递是将数值传递到程序中,这种方式传递是单向传递 但是如果想要双向传递,这种视频无法满足: 引用传递 引用传递可以实现双向的传递 为了对比处两个之间的差异,这里举出两个例 ...

  10. Linux 驱动框架---input子系统

    input 子系统也是作为内核的一个字符设备模块存在的,所以他也是字符设备自然也会有字符设备的文件接口.input子系统的注册过程主要分为两步,先注册了一个input class然后再注册一个字符设备 ...