python copy函数用法_Python深浅拷贝
预备知识一——python的变量及其存储
在详细的了解python中赋值、copy和deepcopy之前,我们还是要花一点时间来了解一下python内存中变量的存储情况。
在高级语言中,变量是对内存及其地址的抽象。对于python而言,python的一切变量都是对象,变量的存储,采用了引用语义的方式,存储的只是一个变量的值所在的内存地址,而不是这个变量的只本身。
引用语义:
在python中,变量保存的是对象(值)的引用,我们称为引用语义。采用这种方式,变量所需的存储空间大小一致,因为变量只是保存了一个引用。也被称为对象语义和指针语义。
值语义:
有些语言采用的不是这种方式,它们把变量的值直接保存在变量的存储区里,这种方式被我们称为值语义,例如C语言,采用这种存储方式,每一个变量在内存中所占的空间就要根据变量实际的大小而定,无法固定下来。
值语义和引用语义的区别:
值语义: 死的、 傻的、 简单的、 具体的、 可复制的
引用语义: 活的、 聪明的、 复杂的、 抽象的、 不可复制的
Paste_Image.png
预备知识二——各基本数据类型的地址存储及改变情况
由于python中的变量都是采用的引用语义,数据结构可以包含基础数据类型,导致了在python中数据的存储是下图这种情况,每个变量中都存储了这个变量的地址,而不是值本身;对于复杂的数据结构来说,里面的存储的也只只是每个元素的地址而已。:
Paste_Image.png
1.数据类型重新初始化对python语义引用的影响
变量的每一次初始化,都开辟了一个新的空间,将新内容的地址赋值给变量。对于下图来说,我们重复的给str1赋值,其实在内存中的变化如下右图:
Paste_Image.png
从上图我们可以看出,str1在重复的初始化过程中,是因为str1中存储的元素地址由'hello world'的地址变成了'new hello world'的。
2.数据结构内部元素变化重对python语义引用的影响
Paste_Image.png
当对列表中的元素进行一些增删改的操作的时候,是不会影响到lst1列表本身对于整个列表地址的,只会改变其内部元素的地址引用。可是当我们对于一个列表重新初始化(赋值)的时候,就给lst1这个变量重新赋予了一个地址,覆盖了原本列表的地址,这个时候,lst1列表的内存id就发生了改变。上面这个道理用在所有复杂的数据类型中都是一样的。
变量的赋值
Paste_Image.png
我们刚刚已经知道,str1的再次初始化(赋值)会导致内存地址的改变,从上图的结果我们可以看出修改了str1之后,被赋值的str2从内存地址到值都没有受到影响。
看内存中的变化,起始的赋值操作让str1和str2变量都存储了‘hello world’所在的地址,
重新对str1初始化,使str1中存储的地址发生了改变,指向了新建的值,此时str2变量存储的内存地址并未改变,所以不受影响。
2.复杂的数据结构中的赋值
刚刚我们看了简单数据类型的赋值,现在来看复杂数据结构变化对应内存的影响。
Paste_Image.png
上图对列表的增加修改操作,没有改变列表的内存地址,lst1和lst2都发生了变化。
对照内存图我们不难看出,在列表中添加新值时,列表中又多存储了一个新元素的地址,而列表本身的地址没有变化,所以lst1和lst2的id均没有改变并且都被添加了一个新的元素。
简单的比喻一下,我们出去吃饭,lst1和lst2就像是同桌吃饭的两个人,两个人公用一张桌子,只要桌子不变,桌子上的菜发生了变化两个人是共同感受的
初识拷贝
我们已经详细了解了变量赋值的过程。对于复杂的数据结构来说,赋值就等于完全共享了资源,一个值的改变会完全被另一个值共享。
然而有的时候,我们偏偏需要将一份数据的原始内容保留一份,再去处理数据,这个时候使用赋值就不够明智了。python为这种需求提供了copy模块。提供了两种主要的copy方法,一种是普通的copy,另一种是deepcopy。我们称前者是浅拷贝,后者为深拷贝。
深浅拷贝一直是所有编程语言的重要知识点,下面我们就从内存的角度来分析一下两者的区别。
1、什么是深浅拷贝 深拷贝和浅拷贝,python中一切皆对象,像数字,字符串,元祖,如果在内存中存储了这些元素,那么这块内存中的值是不可以被修改的,但是还存在一些可变对象,比如列表和字典,他们所占有的内存空间是可以修改的,有因为python中使用的是引用计数去节省内存。
首先我们定义一个列表并引用
list=[1,2,[1,2]]
list1=list
id(list) 140150690045832
id(list1) 140150690045832
注:id函数的意思是返回对象object的标识符,标识符类型为整数,在同一个时间里所有对象的标识符是唯一的,
如果在不同生命周期的对象有可能有相同的标识符。 例如:我们把list中的第一个数改变的话我们发现list1也随之改变,
问什么会出现这种情况呢,这是因为python中使用的是引用计数去节省内存。
list[0]='a'
list['a',2,[1,2]]
list1['a',2,[1,2]]
但是我们往往只想修改list而不改变list1,怎么实现呢我们可以通过切片拷贝
dellist1
list['b',2,[1,2]]
list1=list[:]#切片赋值
list1['b',2,[1,2]]
list[-1][0]='c'#将list[-1][0]修改为字符c
list['b',2,['c',2]]
list1['b',2,['c',2]] #我们发现虽然我们切片操作了, 但是对于里层的列表却没改变
总结一下:当你使用切片操作拷贝的时候,我们修改了外层的列表,外层不随之改变,但是 修改里层的子列表时,却会改变。 除此之外浅拷贝还有第二种方式,及插入copy模块copy模块实现浅拷贝 首先我们删除列表,并插入模块
dellist
dellist1
importcopy定义列表并对外层内层赋值
list=[1,2,[1,2]]
list1=copy.copy(list)#使用copy模块实现赋值
list[1,2,[1,2]]
list1[1,2,[1,2]]
list[-1][0]='a'#里层赋值
list[0]='b'#外层赋值
list['b',2,['a',2]]
list1[1,2,['a',2]] #这里我们发现外层没有随之改变,但是里层却跟着变了,
这就是copy模块实现浅拷贝,但是我们想实现互不影响那我们使用深拷贝
3、深拷贝 使用deepcopy函数 首先我们删除list1并重新赋值
dellist1
list['b',2,['a',2]]
list1=copy.deepcopy(list)
list['b',2,['a',2]]
list1['b',2,['a',2]]
list[0]='c'#对list[0]修改,修改的是外层
list[-1][0]='d' #对list[-1][0]修改,修改的是内层
list['c',2,['d',2]]
list1['b',2,['a',2]]#这里我们发现对list赋值后,list内层外层都没有随之改 变这就是深拷贝。
4、总结:
浅拷贝:不会拷贝数据中的子对象切片拷贝,
importcopy copy.copy()
深拷贝:会拷贝数据中的子对象
importcopy.deepcopy
python copy函数用法_Python深浅拷贝相关推荐
- python copy函数用法_python shutil模块函数copyfile和copy的区别
展开全部 copyfile(src, dst) #src, dst 都需是文件名, 如果dst 存在或无权限,会抛出异常 copy(src, dst) #dst 可以是目录名. shutil.copy ...
- python所有函数用法_python函数用法总结
空函数 如果想定义一个什么事也不做的空函数,可以用pass语句: def nop(): pass pass语句什么都不做,那有什么用?实际上pass可以用来作为占位符,比如现在还没想好怎么写函数的代码 ...
- python自动复制输出_python 深浅拷贝集合
一.深浅拷贝 1.浅拷贝,只会拷贝第一层 s = [1, 'ss', '小可爱'] s1=s.copy()print(s1) >>> [1, 'ss', '小可爱'] s = [1, ...
- python func函数用法_python函数局部变量用法实例分析
本文实例讲述了python函数局部变量用法.分享给大家供大家参考.具体分析如下: 当你在函数定义内声明变量的时候,它们与函数外具有相同名称的其他变量没有任何关系,即变量名称对于函数来说是 局部 的.这 ...
- python func函数用法_Python常见内置高效率函数用法示例
本文实例讲述了Python常见内置高效率函数用法.分享给大家供大家参考,具体如下: 1. filter(function,sequence) 将sequence中的每个元素,依次传进function ...
- python itemgetter函数用法_Python itemgetter函数怎么用?
Operator模块中也有一类函数可以作为条件过滤. 首先介绍 itemgetter 函数.假设定义了一个 f 函数,f = itemgetter(2),那么如果调用 f(r),实际会返回 r[2]. ...
- python pow函数用法_Python代码中pow()函数具有哪些功能呢?
摘要: 下文讲述Python代码中pow()函数的功能说明,如下所示: pow函数功能说明 pow() 函数用于 计算 xy(x 的 y 次方) 的值 pow函数语法: import math mat ...
- python replace函数用法_Python实现的从右到左字符串替换方法示例
本文实例讲述了Python实现的从右到左字符串替换方法.分享给大家供大家参考,具体如下: 一 . 前言 需要用到,但是发现python没有从右边开始替换的内置方法,默认的replace只是从左边开始, ...
- python所有函数用法_Python函数使用方法(高级用法)
前面章节,已经介绍了 Python 函数的所有基本用法和使用注意事项.但是,Python 函数的用法还远不止此,Python 函数还支持赋值.作为其他函数的参数以及作为其他函数的返回值. 首先,Pyt ...
最新文章
- onSaveInstanceState与onRestoreInstance
- java线程同步的五种方法
- Intellij IDEA神器居然还有这些小技巧
- 阿里云常见问题及解决方案:
- boost / vs2017 编译 boost 1.68.0 的过程说明
- 左外连接的sql语句_Django数据库连接和使用原生sql语句
- Java与汽车_Java NIO:IO与NIO的区别
- 【程序员】保持一颗虚心好学的心态去敲代码
- aps后缀是什么文件_APS审核真的取消了么?
- 【SQL Server备份恢复】数据库恢复:对page header的恢复
- 程序猿爆笑选集(1)
- (16)VHDL实现半加器与全加器
- java基础循环 for 、switch 、while 、do while、
- mysql auto_inc_MySQL innodb_autoinc_lock_mode 详解
- SpannableString 给TextView添加不同的显示样式
- 安装terrasolid模块的“setup.exe”弹窗setup.inf not found
- 山寨google, 新做了1个网站 googler.cc ,做的很山寨 喜欢的朋友可以去看看哈
- html的页脚设计,如何单独设置页眉页脚
- 商业综合体能耗在线监测管理系统_商场管理平台
- 联想微型计算机如何设置u盘启动,联想电脑如何设置U盘启动?联想电脑bios设置U盘启动教程...
热门文章
- RT3070_STA_驱动移植文档
- 关于linux内核无法编译成模块的解决方法
- VMware linux 克隆机的配置
- android wheelview 字体颜色,百行代码实现Android WheelView
- 8086的两种工作模式_Buck变换器工作原理
- PyCharm中配置与PyQT5相关的External tools
- java中多线程编程案例_Java中多线程编程实战的实现线程_Java编程_Java程序员_课课家...
- 快手基于 Flink 的持续优化与实践
- mysql 内存越界_linux内存管理浅析
- 建立海盗的天堂:盗贼之海的AI设定(三):巨齿鲨、海怪和骷髅船的AI运行