在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. A - 最长回文(马拉车算法//manacher)

    给出一个只由小写英文字符a,b,c...y,z组成的字符串S,求S中最长回文串的长度.回文就是正反读都是一样的字符串,如aba, abba等 Input输入有多组case,不超过120组,每组输入为一 ...

  2. 2019ICPC南昌邀请赛 Sequence

    题意:给出n个点的权值,m次操作,操作为1时为询问,每次询问给出 l 和 r ,求 f(l,r).操作为0时为修改权值.f(l,r)=f(l,l)⊕f(l,l+1)⊕⋯⊕f(l,r)⊕f(l+1,l+ ...

  3. 【noi 2.6_7627】鸡蛋的硬度(DP)

    题意:其中n表示楼的高度,m表示你现在拥有的鸡蛋个数. 解法:f[i][j]表示 i 层楼有 j 个鸡蛋时,至少要扔多少次.3重循环,k为测试的楼层,分这时扔下去的鸡蛋碎和不碎的情况.要注意初始化. ...

  4. poj 3436 ACM Computer Factory 最大流+记录路径

    题目 题意: 每一个机器有一个物品最大工作数量,还有一个对什么物品进行加工,加工后的物品是什么样.给你无限多个初始都是000....的机器,你需要找出来经过这些机器操作后最多有多少成功的机器(111. ...

  5. Codeforces Round #672 (Div. 2) C1. Pokémon Army (easy version) (DP)

    题意:给你一组数\(a\),构造一个它的子序列\(b\),然后再求\(b_1-b2+b3-b4...\),问构造后的结果最大是多少. 题解:线性DP.我们用\(dp1[i]\)来表示在\(i\)位置, ...

  6. Python进阶丨如何创建你的第一个Python元类?

    摘要:通过本文,将深入讨论Python元类,其属性,如何以及何时在Python中使用元类. Python元类设置类的行为和规则.元类有助于修改类的实例,并且相当复杂,是Python编程的高级功能之一. ...

  7. LINUX - mmap()

    内存映射函数 https://blog.csdn.net/qq_33611327/article/details/81738195

  8. hdu2333-贪心,如何去后效性,背包太大怎么办,如何最大化最小值,从无序序列中发掘有序性质

    补充一下我理解的中文题意.. 你要重新组装电脑..电脑有一些部件..你的预算有b,b(1~1e9),有n个部件..每个部件有类型和名称以及价钱和质量现在你要在不超过预算b的情况下..每个类型都买一个部 ...

  9. 高并发之Semaphore、Exchanger、LockSupport

    本系列研究总结高并发下的几种同步锁的使用以及之间的区别,分别是:ReentrantLock.CountDownLatch.CyclicBarrier.Phaser.ReadWriteLock.Stam ...

  10. vue watch route params change

    vue watch route params change watch: { '$route.params.menuKey' (val, oldVal) { console.log('new rout ...