引入

  在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. Python import用法

    官方文档说明: Python code in one module gains access to the code in another module by the process of impor ...

  2. Spring对JSON请求加解密

    Spring中处理JSON请求通常使用@RequestBody和@ResponseBody注解,针对JSON请求加解密和过滤字符串,Spring提供了RequestBodyAdvice和Respons ...

  3. 修改windows7本地策略--不能挂载磁盘和复制 -- 黏贴板-驱动器映射

    1.gpedit.msc -- > 计算机配置-- > 管理模板 -- > windows 组件 -- > 远程桌面服务 -- > 远程桌面服务主机 -- > 设备 ...

  4. 网易云音乐 歌词制作软件 BesLyric (最新版本下载)

    导读 BesLyric , 一款专门制作 网易云音乐 LRC 滚动歌词的软件! 搜索.下载.制作 歌词更方便! 哈哈,喜欢网易云音乐,又愁于制作歌词的童鞋有福啦!Beslyric 为你排忧解难! 本文 ...

  5. oracle 相除后保留指定位数小数round()

    ) xxx from dual; XXX----------    3.8871

  6. odoo学习之带出信息

    # 输入客户带出它默认的发运方式和包装方式 def on_change_partner_id_return(self,cr,uid,ids,partner_id,context=None): resu ...

  7. JS-JS创建数组的三种方法

    隐式创建 var arr=["Audi","BMW","Volvo"]; 直接实例化 var arr=new Array("Aud ...

  8. 解决webapi首次启动速度慢的问题 - z

    原理与下面两篇文章提及的相同 https://blog.csdn.net/godcyx/article/details/38517135 http://www.huaface.com/p/12

  9. CRC---循环冗余校验

    typedef unsigned char uchar; typedef unsigned int uint; typedef unsigned short uInt16; uint crc; // ...

  10. ASP.NET Core使用TopShelf部署Windows服务

    asp.net core很大的方便了跨平台的开发者,linux的开发者可以使用apache和nginx来做反向代理,windows上可以用IIS进行反向代理. 反向代理可以提供很多特性,固然很好.但是 ...