码迷,mamicode.com
首页 > 编程语言 > 详细

python 变量、 赋值、浅拷贝、深拷贝

时间:2020-07-11 00:02:08      阅读:68      评论:0      收藏:0      [点我收藏+]

标签:变量赋值   垃圾   存储   com   导致   mamicode   直接   申请   参数   

Python中的变量 

  Python中的变量可以看作数值的一个标签,当给变量赋值时,该变量将指向该值域的存储空间,给该变量重新赋一个新值时,将释放当前值域的存储空间,指向另一个值域存储空间。

技术图片

  对于Python来说是以值域为内存分配对象,变量名只是指向该内存空间,当值域发生变化时,系统分配另外一块内存,该变量指向新分配的地址块,原来地址空间系统进行回收,该方式也就说明了为何python的变量可以为任何类型,而C/C++则是先给变量分配一块适当的大小,当值变化时,直接更新变量指向地址的内存块,及变量的地址永远不变,所以它就必须为固定的类型。

  python中可以通过id(a)来查看变量a的地址,例如如下测试:

技术图片

当存在如下情况时:

技术图片

  a = 100, b = 100 时,此时id(a) 和id(b)是相等的,但是当a = 7823.232, b = 7823.232时,此时id(a)和id(b)的地址有可能相同也有可能不同,这个取决于计算机系统(32位上测试不同,64位上相同)。python对[-5, 257]区间的整数和短字符串做了内存缓存,当不同的变量等于同一个值时,变量的地址都相同,其他的数会各自维护一个地址空间。

变量赋值

  Python中变量的赋值,其实是地址的引用,比如a = 0, b = a,a和b将指向同一块地址,当b = 10的时候,b又指向了另外的一块地址空间。

技术图片

浅拷贝

  变量赋值是地址的引用,比如链表 [1, 2, 3, 4],如果进行赋值操作,我们对变量的任意改变都将导致另一个变量值的改变。

技术图片

   我们可以发现,对任何一个变量的修改都会导致另一个变量值的变化。我们可以使用copy模块进行内存空间的拷贝。

技术图片

   此时a和b各自拥有一块独立的空间,但是如下情况

技术图片

 [‘aa‘, ‘bb‘, ‘cc‘]为嵌套链表,此时修改a和b中嵌套的链表,a,b变量中的值都会被更改。

上面的情况就是浅拷贝,最外层会独立创建一块独立空间,但是内部嵌套的复合类型采用的依然为地址引用。

要解决上面问题,使得a和b的存储空间完全独立,就要采用深拷贝。

深拷贝

对于上面问题,我们采用深拷贝,将得到如下结果

技术图片

 深拷贝将拷贝a变量的所有存储空间,a, b完全占有独立的存储空间

赋值,浅拷贝,深拷贝关系如下图

技术图片

 变量的引用计数

既然Python的变量都是地址的引用,那么如果 a = b后,把a释放掉,b会一起释放空间吗?

技术图片

我们发现,当del a后,b的地址并没有发生变化,而且b的值也没被释放。

这是因为在赋值(地址引用)时,会有个计数器,当引用增加时,计数器对应增加,引用减少(释放或者生命周期结束),计数器对应减少,当计数器减少到0的时候,启动系统垃圾回收机制对存储空间进行回收,当然Python的内存回收不会当计数器减少为0时马上回收,如果一段时间内,有新的内存申请需要,则会复用现在的内存空间,否则就释放。

我们可以使用 sys.getrefcount() 查看变量被引用的次数

技术图片

 我们发现,为啥计数从2开始呢,其实这个是因为调用函数getrefcount时,参数传递时,也进行了一次地址的引用,所以比实际的引用会多一次。

 

python 变量、 赋值、浅拷贝、深拷贝

标签:变量赋值   垃圾   存储   com   导致   mamicode   直接   申请   参数   

原文地址:https://www.cnblogs.com/lwp-boy/p/13269681.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!