引入

  在python程序中,如果我们操作一个变量的值去做运算,而又想在下次调用时,仍使用原来的变量的值去做运算,那么我们我们就需要将这个变量去做备份,这就是本文所要探究的问题。

开始

变量-对象-引用:
  python中全部皆对象,Python中变量是指对象(甚至连type其本身都是对象,type对象)的引用,Python是动态类型,程序运行时候,会根据对象的类型来确认变量到底是什么类型。

我们有时候会见到这样一种情况:

  a = 1

  b = a

这样做不就是把数据copy了一份吗,错,这样做只是在程序中新创建了一个对象b,去引对象a创建是指定的值,也就是说,它们是指向了同一块内存地址,而不是在创建 b = a 时又重新在内存中开辟出一块空间来,所以当一个变量的值被修改,则另一个变量的值也会随之被修改,这样说可能不太理解,来个图示吧:

这个叫做"共享引用",而不是做一个副本(不要犯这样的错哦)。

正题

现在就开始探究一下深浅copy

深浅copy的方法由python内置的一标准库提供(提供的copy方法,适合所有类型对象)
简单点说

  • copy.copy 浅拷贝 只拷贝父对象,不会拷贝对象的内部的子对象。
  • copy.deepcopy 深拷贝 拷贝对象及其子对象

用一个简单的例子来说明一下

>>> import copy
>>> a = [1,2,3,['a','b','c']]
>>> b = a
>>> c = copy.copy(a)
>>> d = copy.deepcopy(a)

a是一个列表,表中的a[3]也是一个列表(也就是一个内部的子对象),b是对a列表的又一个引用,所有a,b是完全相同的,我们可以通过id(a)来验证。

>>> id(a)
60356208
>>> id(b)
60356208
>>> id(c)
63132896
>>> id(d)
63133256

a 和 b的相同也证实了前面所说的共享引用;

深浅copy的区别:

浅copy

>>> import copy
>>> a = [1,2,3,['a','b','c']] #a具有两级对象的列表
>>> b = copy.copy(a) #创建变量b,使其浅copy a的值
>>> b
[1, 2, 3, ['a', 'b', 'c']]
>>> a[1] = "two" #当a的父对象修改之后而b的父对象不会被修改
>>> a
[1, 'two', 3, ['a', 'b', 'c']]
>>> b
[1, 2, 3, ['a', 'b', 'c']]
>>> a[3][0] = 'A' #当a的子对象被修改之后b的子对象也会随之修改
>>> a
[1, 'two', 3, ['A', 'b', 'c']]
>>> b
[1, 2, 3, ['A', 'b', 'c']]

深copy

>>> import copy
>>> a = [1,2,3,['a','b','c']] #a具有两级对象的列表
>>> b = copy.deepcopy(a) #创建变量b,使其深copy a的值
>>> b
[1, 2, 3, ['a', 'b', 'c']]
>>> a[1] = "two" #当a的父对象修改之后而b的父对象不会被修改
>>> a
[1, 'two', 3, ['a', 'b', 'c']]
>>> b
[1, 2, 3, ['a', 'b', 'c']]
>>> a[3][0] = 'A' #当a的子对象被修改之后b的子对象仍不会随之修改
>>> a
[1, 'two', 3, ['A', 'b', 'c']]
>>> b
[1, 2, 3, ['a', 'b', 'c']]

浅拷贝是指拷贝的只是原对象元素的引用,换句话说,浅拷贝产生的对象本身是新的,但是它的内容不是新的,只是对原对象的一个引用

>>> aList=[[1, 2], 3, 4]
>>> bList = aList[:] #利用切片完成一次浅拷贝
>>> id(aList)
3084416588L
>>> id(bList)
3084418156L
>>> aList[0][0] = 5
>>> aList
[[5, 2], 3, 4]
>>> bList
[[5, 2], 3, 4]

但是有点需要特别提醒的,如果对象本身是不可变的,那么浅拷贝时也会产生两个值

>>> aList = [1, 2]
>>> bList = aList[:]
>>> bList
[1, 2]
>>> aList
[1, 2]
>>> aList[1]=111
>>> aList
[1, 111]
>>> bList
[1, 2]

为什么bList的第二个元素没有变成111呢?因为数字在python中是不可变类型!!

在这顺便回顾下Python标准类型的分类:

  • 可变类型: 列表,字典
  • 不可变类型:数字,字符串,元组

理解了浅拷贝,深拷贝是什么自然就很清楚了。
python中有一个模块copy,deepcopy函数用于深拷贝,copy函数用于浅拷贝。
最后,对象的赋值是深拷贝还是浅拷贝?
对象赋值实际上是简单的对象引用

>>> a = 1
>>> id(a)
135720760
>>> b = a
>>> id(b)
135720760

a和b完全是一回事。

python深浅copy探究的更多相关文章

  1. Python 深浅copy 和文件操作

    深浅copy 1,先看赋值运算. l1 = [1,2,3,['barry','alex']] l2 = l1 l1[0] = 111 print(l1) # [111, 2, 3, ['barry', ...

  2. python深浅copy

    预备知识一——python的变量及其存储 在详细的了解python中赋值.copy和deepcopy之前,了解一下python内存中变量的存储情况. 在高级语言中,变量是对内存及其地址的抽象.对于py ...

  3. python深浅copy和赋值

    Python直接赋值,浅copy和深copy的比较 基于引用和对象(python引用和对象分离) 总结: 直接赋值:a = b -->a,b两个引用指向相同的对象 浅copy:a为b的copy ...

  4. Python——深浅Copy

    1. 赋值 赋值:指向同一块内存地址,所以同时改变 l1 = [1,2,3] l2 = l1 l1.append('a') print(l1,l2) # [1, 2, 3, 'a'] [1, 2, 3 ...

  5. python 深浅copy的例子

    1. copy.copy 浅拷贝 只拷贝父对象,不会拷贝对象的内部的子对象.2. copy.deepcopy 深拷贝 拷贝对象及其子对象一个很好的例子:import copya = [1, 2, 3, ...

  6. python 深浅copy总结

    总结: ''' 总结:假设l1为原数据,l2为deepcopy后的数据: 1.浅copy,只能改变第一层的内存地址(不可变数据类型除外). 2.深copy,能够改变第一层和第二层的内存地址(不可变数据 ...

  7. 番外:深浅copy

    进击のpython 深浅copy copy是什么意思? 复制 (又学一个单词!开不开森) 那啥叫复制呢? 百度百科上给的解释是:仿原样品制造 我们曾经有过这样的印象 a = "zhangsa ...

  8. python基础3(元祖、字典、深浅copy、集合、文件处理)

    本次内容: 元祖 字典 浅copy和深copy 集合 文件处理 1.1元祖 元祖(tuple)与列表类似,不同之处在于元祖的元素不能修改,元祖使用小括号(),列表使用方括号[].元祖创建很简单,只需要 ...

  9. python学习笔记三 深浅copy,扩展数据类型(基础篇)

    深浅copy以及赋值 对于字符串和数字而言,赋值.浅拷贝和深拷贝无意义,因为其永远指向同一个内存地址. import copy n1 = #n1 = 'hahahaha' #赋值n2 = n1#浅co ...

随机推荐

  1. mysql5.6.8源码安装

    内核: [root@opop ~]# cat /etc/centos-release CentOS release 6.8 (Final)[root@opop ~]# uname -aLinux op ...

  2. 稳压二极管&TVS二极管

    稳压二极管 稳压二极管利用的特性是:二极管被反向击穿之后,随着电流的变化,稳压二极管两端电压维持不变的特性: 普通二极管反向击穿后就坏了,但是稳压二极管却可以恢复,而且在被击穿后处在正常的工作状态: ...

  3. Java多线程编程模式实战指南(三):Two-phase Termination模式

    停止线程是一个目标简单而实现却不那么简单的任务.首先,Java没有提供直接的API用于停止线程.此外,停止线程时还有一些额外的细节需要考虑,如待停止的线程处于阻塞(等待锁)或者等待状态(等待其它线程) ...

  4. NPOI DataTable导出excel

    /// <summary> /// DataTable导出到Excel文件 /// </summary> /// <param name="dtSource&q ...

  5. 《Head First 设计模式》[02] 观察者模式

    1.观察者模式 1.1 形象地认识观察者模式 报社的业务是出版报纸 用户像某家报社订阅了报纸,那么一旦报社有新的报纸,就会送到用户处.只要是订户,就一直会收到新报纸: 当用户不再想看报纸时,取消订阅, ...

  6. NoSql的三大基石:CAP理论&BASE&最终一致性

    关系型数据库的局限 NoSql出现在关系型数据库之后,主要是为了解决关系型数据库的短板,我们先来看看随着软件行业的发展,关系型数据库面临了哪些挑战: 1.高并发 一个最典型的就是电商网站,例如双11, ...

  7. 洛谷 P4409 [ZJOI2006] 皇帝的烦恼

    题目链接-> OVO 题解: 很久没有写博客了,可能是因为最近太颓废了吧. 刚刚考完期末考试,无比期盼早点外出学习,不要面对成绩,害怕. #include <cstdio> #inc ...

  8. Ubuntu 打包后安装提示:子进程 已安装 pre-removal 脚本 返回了错误号 1

    子进程 已安装 pre-removal 脚本 返回了错误号 1或2 与 子进程 已安装 post-installation 脚本 返回了错误号 1或2   一.子进程 已安装 pre-removal  ...

  9. python语言程序设计7

    1, 特么的打个空格出现就出现个点是个怎么回事, 昨天虽然是我复制的代码,,但也是我一点一点写出来的啊.. 复制的时候缩进直接就没了.我去 但是我感觉它一开始给我讲的一些基础理论又有点忘了,我希望你能 ...

  10. MVC_防止HttpPost重复提交

    重复提交的场景很常见,可能是当时服务器延迟的原因,如购物车物品叠加,重复提交多个订单.常见的解决方法是提交后把Button在客户端Js禁用,或是用Js禁止后退键等.在ASP.NET MVC 3 Web ...