引入

  在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. MySQL 基础十 性能优化

    1.优化sql 2.建立索引 3.优化表结构,避免多个join查询

  2. Image Restoration[Deep Image Prior]

    0.背景 这篇论文是2017年11月29号第一次提交到arxiv并紧接着30号就提交了V2版本的. 近些年DCNN模型在图像生成和修复上面表现很好,大部分人认为好的原因主要是由于网络基于大量的图片训练 ...

  3. Linux tar 解压 压缩(转)

     注:tar是打包,不是压缩!)  解包: tar xvf FileName.tar 打包:tar cvf FileName.tar DirName .tar.gz 解压:tar zxvf FileN ...

  4. R语言学习 第十篇:包

    包(Package)是实现特定功能的.预先写好的代码库(library),通俗地说,包是含有函数.数据等的功能模块.R拥有大量的软件包,许多包都是由某一领域的专家编写的,但并不是所有的包都有很高的质量 ...

  5. 一文让你完全弄懂Stegosaurus

    国内关于 Stegosaurus 的介绍少之又少,一般只是单纯的工具使用的讲解之类的,并且本人在学习过程中也是遇到了很多的问题,基于此种情况下写下此文,也是为我逝去的青春时光留个念想吧~ Stegos ...

  6. 浅谈JS的作用域链(一)

    JS的执行环境 执行环境(Execution context,EC)或执行上下文,是JS中一个极为重要的概念. 在JavaScript中有三种代码运行环境: Global Code JavaScrip ...

  7. Educational Codeforces Round 49 (Rated for Div. 2)A到C题

    A题意 给你t表示有t组测试数据,每组数据给你一个含小写字母的字符串,每个字符必须变为它相邻的字符,问最后是否能变成回文串.a不能变成z,反过来也不行 分析 只需对对称位置判断差是否小于2且不等于1, ...

  8. IT行业的创新的读后感

    一.什么是创新 创新是以新思维.新发明和新描述为特征的一种概念化过程.它原意有三层含义,第一,更新:第二,创造新的东西:第三,改变.创新是人类特有的认识能力和实践能力,是人类主观能动性的高级表现形式, ...

  9. 第七组团队项目——专业课程资源共享平台——需求分析&原型设计

    一.项目目标.定位需求: (1)目标:在教师.学生之间建立一个综合的.全面的.快捷的.高效的免费课程和学习资源共享.交流与推荐的开放性平台,实现多维和动态的推荐与分类检索服务. (2)定位:学生与教师 ...

  10. VS2015 导航栏 查看每个cpp文件中类以及类成员函数的框框

    这个可以查看每个cpp文件中类以及类成员函数的框框叫导航栏! 怎么打开导航栏可以再百度.