Python内存管理-引用计数-垃圾回收机制(通俗易懂)
Python内存管理-垃圾回收机制
1. Python引用计数
首先,什么是引用计数?
说到引用计数,就得先了解什么是python对象
1.1 python对象
python中一切皆对象(数字、字符串、元组、列表、字典、函数、方法、类、模块),Python的万物皆对象从感性上可以解释为:Python 中的一切都可以赋值给变量或者作为参数传递给函数。
1.1.1 Python的所有对象都有三个特性:
(1)函数 id() ,每个对象都有一个唯一的身份标识,即该对象的内存地址
(2)函数 type() 来查看对象的类型,对象的类型决定了对象可以保有哪些属性和方法,可以进行哪些操作,遵循怎样的规则
(3)函数 sys.getrefcount()方法查看对象的引用计数
当使用sys.getrefcount查看-5到256之内的数字对象时,会发现引用计数非常大,这是因为python自己创建了-5到256内的所有数字对象,且引用很多,不用用户再创建,具体详情可搜索 小数据池 。
(4)函数 del 对象,可以删除内存中对象
引用计数:
对象都包含了两个头部信息,一个是类型标志符,标识这个对象的类型;另一个是引用计数器,记录当前指向该对象的引用数目,表示这个对象被多少个变量名所引用。
a=1000
a是变量名,1000是创建在内存中的实际对象,“=”将1000在内存中的地址给a变量值(python中赋值,参数传递 都是原对象地址的传递),1000的引用计数+1
2. Python垃圾回收(简单基础版)
在Python中每一个对象的核心就是一个结构体PyObject,它的内部有一个引用计数器(ob_refcnt)。程序在运行的过程中会实时的更新ob_refcnt的值,来反映引用当前对象的名称数量。当某对象的引用计数值为0,那么它的内存就会被立即释放掉。当然循环引用也会被释放。
2.1引用计数变化的情况
以下情况是导致引用计数加一的情况:
对象被创建,例如a=2
对象被引用,b=a
对象被作为参数,传入到一个函数中
对象作为一个元素,存储在容器中
下面的情况则会导致引用计数减一:
对象别名被显示销毁 del
对象别名被赋予新的对象
一个对象离开他的作用域
对象所在的容器被销毁或者是从容器中删除对象
3.何时python会自动启动垃圾回收?
垃圾回收时,Python不能进行其它的任务。频繁的垃圾回收将大大降低Python的工作效率。如果内存中的对象不多,就没有必要总启动垃圾回收。所以,Python只会在特定条件下,自动启动垃圾回收。当Python运行时,会记录其中分配对象(object allocation)和取消分配对象(object deallocation)的次数。当两者的差值高于某个阈值时,垃圾回收才会启动扫描。
gc模块的get_threshold()方法,查看该阈值
4.手动启动垃圾回收机制
使用gc.collect()
5.扫描策略--分代回收
垃圾回收是先扫描再回收,但扫描时并不是使用对象都一视同仁一起扫描。
Python将所有的对象分为0,1,2三代。所有的新建对象都是0代对象。当某一代对象经历过垃圾回收,依然存活,那么它会归入1代对象。垃圾回收启动时,一定会扫描所有的0代对象。如果0代经过一定次数垃圾回收,那么就启动对0代和1代的扫描清理。当1代也经历了一定次数的垃圾回收后,那么会启动对0,1,2,即对所有对象进行扫描。
get_threshold()
返回(700, 10, 10)元组,其中两个10。第一个10表示,每10次0代垃圾回收,会配合1次1代的垃圾回收;第二个10表示:而每10次1代的垃圾回收,才会有1次的2代垃圾回收。
同样可以用set_threshold()来调整,比如对2代对象进行更频繁的扫描。
import gc
gc.set_threshold(700, 10, 5)
posted on 2022-08-19 09:41 hzk-shzdx-university 阅读(217) 评论(0) 编辑 收藏 举报