对象引用与垃圾回收

这个世界很温柔,但它不喜欢我。

变量

Python作为静态语言,他的变量与其他语言的变量是不一样的。比如java中的变量你需要提前申明,定义数据类型,然后交给虚拟机执行。但是在python中的变量,本质上是一个指针,举个例子。

a = 1

python会做如下步骤:

  1. 在内存中申请一块内存空间存储一个int类型的对象
  2. 生成int类型的对象
  3. 最后把变量a指向数字1上面
  4. 可以把多个变量指向同一个对象

所以说,python中变量其实是一个指针,指向不同的对象。

is 与 ==

在深入类与对象-上中提起到is与==的区别:

这一开头就介绍了类的三大特性,类型(type),值(value),身份(id)

is:只要id相同,就返回True
==:只要value相同,就返回True

比如 1 == 1.0就返回True,1 is 1.0 就返回False。

注意了,这里变量都是不可变的类型,数字,字符串,浮点数都是不可变的(这里其实是python的小整形小字符串指向的都是同一个指针),所以使用is他们的id都是一样的,并且你定义一个类,实例化给a和b(不传入参数),他们的id也是一样的,如果实例化后传入参数,即使参数一样的,那他们的id也是不一样的。

但是对于list,set,dict这种可变的数据类型来说id也是不一样的。

垃圾回收

定义

python中的垃圾回收是以引用计数为主,标记-清除和分代收集为辅。

引用计数:python在内存中存储每个对象的引用计数,如果计数变成0,该对象就会消失,分配给该对象的内存就会释放出来。

标记-清除:一些容器对象,比如说list、dict、tuple、instance等可能会出现引用循环,对于这些循环,垃圾回收器会定时回收这些循环(对象之间通过引用(指针)连在一起,构成一个有向图,对象构成这个有向图的节点,而引用关系构成这个有向图的边)。

分代收集:python把内存根据对象存活时间划分为三代,对象创建之后,垃圾回收器会分配它们所属的代。每个对象都会被分配一个代,而被分配更年轻的代是被优先处理的,因此越晚创建的对象越容易被回收。

讲解

python的垃圾回收算法是引用计数为主,举个例子:

a = 100
b = a

这里python做了两步:

  1. 在100这个对象上,会有一个计数器,因为定义变量a=100,那么计数器的数值为1
  2. 然后又让b指向了a,本质上是b的指针也指向了100,这个时候100这个对象的计数器的数值为2
  3. 也就是说目前100这个对象的有两个变量指向他,计数器值是2

一开始在dict中介绍过,删除字典的某一对键值使用 del dict[‘user’],那么删除其他变量也是一样的,使用del即可。这个时候删除a

del a

这个时候100的计数器的值为1了,但是这个时候python并没有对100回收,因为之后当计数器的数值为0的时候才会回收100,这个时候你del a后,使用print(b)是没问题的,因为这个时候100这个对象还没有完全清除。

在一开始的魔法函数中,有__del__这个魔法函数,你定义的类中使用这个魔法函数,当你的类实例化运行完成后,需要回收垃圾的时候,就会调用这个del魔法函数,做你想要完成的事情。

Python垃圾回收机制

内存池机制

Python提供了对内存的垃圾收集机制,但是它将不用的内存放到内存池而不是返回给操作系统。

1,Pymalloc机制。为了加速Python的执行效率,Python引入了一个内存池机制,用于管理对小块内存的申请和释放。

2,Python中所有小于256个字节的对象都使用pymalloc实现的分配器,而大的对象则使用系统的malloc。

3,对于Python对象,如整数,浮点数和List,都有其独立的私有内存池,对象间不共享他们的内存池。也就是说如果你分配又释放了大量的整数,用于缓存这些整数的内存就不能再分配给浮点数。

坚持原创技术分享,您的支持将鼓励我继续创作!
------ 本文结束 ------

版权声明

LangZi_Blog's by Jy Xie is licensed under a Creative Commons BY-NC-ND 4.0 International License
由浪子LangZi创作并维护的Langzi_Blog's博客采用创作共用保留署名-非商业-禁止演绎4.0国际许可证
本文首发于Langzi_Blog's 博客( http://langzi.fun ),版权所有,侵权必究。

0%