Python中的引用赋值,深拷贝,浅拷贝

摘要:Python引用赋值深拷贝浅拷贝

总结一下Python中的变量的引用赋值,深拷贝和浅拷贝,先上结论

  • 赋值引用会直接将内存地址传递过去,此时变量间不仅值相等内存地址也相等,是同一个对象

  • 赋值存在缓存重用的情况,当重复定义小整数字符串变量时,或者在同一个代码块中,内存中已经存在的值会直接被引用,不需要重新创建对象。

  • 组合变量存在赋值引用深拷贝浅拷贝三种模式,赋值引用将组合对象的每一层地址全部引用,浅拷贝创建新对象,但是内部元素引用旧对象的内部元素,深拷贝所有地址全部重新创建,不依赖之前任何的内存地址。

  • 和原始对象的关系或者联系紧密程度:赋值引用 > = 浅拷贝 >= 深拷贝

  • 内存的复用程度:赋值引用 > = 浅拷贝 >= 深拷贝

  • 变量的崭新程度:深拷贝 >= 浅拷贝 >= 赋值引用

引用赋值

在python中,使用等号无论是直接的变量赋值,还是参数传递,都是按照引用进行赋值的,等号赋值是指将对象的内存指针赋值
在Python中对于非组合变量(对象中不包含其他对象,只有一层地址关系)的赋值直接使用等号赋值即可,即将一个变量赋值给另一个变量,则两者不仅在数值上相等,而且还是同一对象id相同is判断为True这两个变量都指向这一个数据对象,即这个数据对象有两个引用,只有这两个引用都没了的时候,堆内存中的数据对象才会等待垃圾回收器回收

如果单独对两个变量赋值,就算赋值的数据对象相同,也只是数据对象的值相等,两个变量在堆内存中是不同的对象


可变对象,不可变对象对引用赋值的影响

如果变量的值是不可变对象,比如string,int,float,tuple等,其中一个变量重新赋值意味着在内存中要新创建一个数据对象,此时变量间不会相互影响,即不会影响另外一个变量。

不可变对象赋值引用改变变量值.png

对于可变对象,调用自身方法使的值改变不会改变内存地址。比如列表list,字典dict,集合set,如果是在原数据对象自身上做修改,比如修改列表中的某个元素,列表的地址不会变,还是原来的那个内存对象,此时调用另一个变量的值也会改变,因为是同一个内存对象的两个引用,因此对于可变对象的引用赋值,变量之间是相互影响的。

可变对象赋值引用改变变量值.png

缓存的重用机制

Python会根据对象的读取频繁程度以及内存占用情况,按照一定规则将对象存入缓存。当程序的其他代码使用这些值的时候,会先去缓存中找并且直接引用缓存中的地址,不需要额外创建,这些值包括:[-5, 256]之间的小整数字符串对象

超过256分别赋值就是不同对象了

字符串是直接读取缓存中地址

除此之外,其他不可变变量如果处在同一个代码块或者同行,也直接获取代码块中缓存的变量,不再另外创建

同一个函数代码块

深拷贝和浅拷贝

首先深拷贝和浅拷贝是针对组合对象的,组合对象就是这个对象中还包含其他对象,比如list,set,dict等,也就是说这个对象有不止一层内存地址,非组合对象都是直接等号赋值。

  • 浅拷贝创建一个新的组合变量,但是组合变量中每一个元素指向拷贝的对象内元素地址

  • 深拷贝创建一个新的组合变量,原对象中的每个元素都会在新对象中重新创建一次

对于组合对象list,set,dict(没有tuple)自带copy浅拷贝方法,深拷贝需要导入copy模块,调用deepcopy方法,copy的copy方法对应浅拷贝

浅拷贝后新对象地址不一样,但是内部元素引用一致


深拷贝新建了一个对象,但是内部元素也是引用的原始地址,原因是内部元素是小整数,小整数在内存中有缓存直接调用,换一下内部元素为可变对象。

原型毕露,深拷贝不仅对象,连对象内部的元素都重新创建,在用新数据试下浅拷贝

厉害,浅拷贝只是创建新对象,内部元素还是老的引用。


在对比一下组合对象的赋值引用

可见赋值引用所有地址全部拷贝去了,既不要创建新对象,内部元素也全是来的对象内部元素的引用。

总结

  • 赋值引用会之间将内存地址传递过去,此时变量间不仅值相等内存地址也相等,是同一个对象

  • 分别赋值存在缓存重用的情况,当重复定义小整数字符串变量时,或者在同一个代码块中,内存中已经存在的值会直接被引用,不需要重新创建对象。

  • 组合变量存在赋值引用深拷贝浅拷贝三种模式,赋值引用将组合对象的每一层地址全部引用,浅拷贝创建新对象,但是内部元素引用旧对象的内部元素,深拷贝所有地址全部重新创建,不依赖之前任何的内存地址。

最后再用一个例子对比一下组合对象的三种拷贝方式

(0)

相关推荐

  • 说说实例句柄和模块句柄的区别

    蝎子 在今天的时代,它们两者已经是同一个东西了,但是在过去的一段时间里,它们确实指代不同的东西.这个过去的时间,实际是远古时期的16位Windows时代.那个时候,一个模块(module)表示一个从磁 ...

  • 【C语言更新】指向数组的指针

    文/Edward 前面我们在讲述数组的时候曾经说过,对于数组内部元素的引用方式主要有两种,一种就是使用方括号"[ ]"的下标索引,另一种就是之前提到过,但是没有细致讲述的指针引用. ...

  • 面试题-python 浅拷贝和深拷贝(copy模块)

    前言 面试的时候经常会问到深拷贝和浅拷贝,那么python的深拷贝和浅拷贝有什么区别呢? 思考题 先来看 2 个简单的案例, 对元素 a/aa 重新赋值一个新的变量 b/bb 后,改变原来 a/aa ...

  • 【Python面试】 说说Python可变与不可变数据类型?

    公众号新增加了一个栏目,就是每天给大家解答一道Python常见的面试题,反正每天不贪多,一天一题,正好合适,只希望这个面试栏目,给那些正在准备面试的同学,提供一点点帮助! 小猿会从最基础的面试题开始, ...

  • 第118天:Python 之对象的比较与拷贝

    众所周知,Python 是一门面向对象语言,在 Python 的世界一切皆对象,那么我们如何判断两个对象是否是同一个对象呢. == 操作符和 is 相信大家对于这两个操作符都不陌生.具体来说就是 == ...

  • Python中深拷贝与浅拷贝的区别?

    公众号新增加了一个栏目,就是每天给大家解答一道Python常见的面试题,反正每天不贪多,一天一题,正好合适,只希望这个面试栏目,给那些正在准备面试的同学,提供一点点帮助! 小猿会从最基础的面试题开始, ...

  • 准算法工程师从30+场秋招中总结出的超强面经—C、Python与算法篇篇(含答案)

    作者丨灯会 来源丨极市平台 编辑丨极市平台 极市导读 作者灯会为21届中部985研究生,七月份将入职某互联网大厂cv算法工程师.在去年灰飞烟灭的算法求职季中,经过几十场不同公司以及不同部门的面试中积累 ...

  • 赋值、浅拷贝和深拷贝

    三种方法的形式存在一定的类似,但是也存在各个之间不相同的地方. 浅拷贝和深拷贝是用在对象(Object)或者数组(Array)这样的数据类型拷贝赋值时候的说法,而赋值操作也可以用在基础的数据类型,如N ...

  • 干货 | 参考文献在论文中正确引用的方法

    一.当文内引用采用姓名和年份的方式,则以时间顺序在文内列出多个文献,再以字母顺序在文后列出这些文献. 当文内引用采用文献号,则以数字顺序在文内和文后列出文献. 二.不同的期刊因其风格差异可能有不同的引 ...

  • C/C++编程笔记:C++中的引用!(含引用和指针的对比)

    当将变量声明为引用时,它将成为现有变量的替代名称.通过在声明中添加"&",可以将变量声明为引用. C++: 输出: x = 20 ref= 30 应用范围:  修改函数中传 ...

  • Python 中的函数装饰器和闭包

    函数装饰器可以被用于增强方法的某些行为,如果想自己实现装饰器,则必须了解闭包的概念. 装饰器的基本概念 装饰器是一个可调用对象,它的参数是另一个函数,称为被装饰函数.装饰器可以修改这个函数再将其返回, ...

  • Python中tuple和list的区别?基础学习!

    想必大家都知道,Python数据类型有很多种,其中有两个对象的写法非常相似,它就是tuple元组和list列表,让人傻傻分不清楚.那么你知道Python中tuple和list有什么区别吗?我们来看看具 ...

  • Python中缩进是什么?入门分享!

    众所周知,Python是一门独特的编程语言,它语法清晰.简单易学,而且Python是通过缩进来识别代码块的,因为一般的语言都是通过{}或者end来作为代码块标记. Python中缩进是什么? 要求严格 ...

  • python中的内置函数

    前言 本人只在csdn写博客 内置函数 介绍 一. 数学运算 abs()求绝对值函数 round() 近似取值 pow()求指数 divmod()求商和余数 max()求最大值和min()求最小值 s ...

  • 【Python核心编程笔记】一、Python中一切皆对象

    Python中一切皆对象 本章节首先对比静态语言以及动态语言,然后介绍 python 中最底层也是面向对象最重要的几个概念-object.type和class之间的关系,以此来引出在python如何做 ...