垃圾收集 (PY高级编程系列)

本文深入探讨了Python的内存管理,包括引用计数和隔代回收机制。通过实例展示了引用计数如何影响对象的生命周期,以及当出现循环引用时,Python如何利用隔代回收来解决。同时,介绍了`gc`模块的相关使用,如设置回收阈值和检查待回收对象数量。
摘要由CSDN通过智能技术生成

垃圾收集-引用计数机制

python采用的是引用计数机制为主,隔代回收机制为辅的策略

栈内存与堆内存

栈内存 存放变量名 里面有个变量可以指向堆内存的值位置(内存地址)

堆内存 对象(值)

在Python中,每个对象都有指向该对象的引用总数—引用计数
当使用某个引用作为参数, 传递给 getrefcount() 时, 参数实际上创建了一个临时的引用
因此, getrefcount() 所得到的结果, 会比期望的多1

import sys


class Test(object):
    def __init__(self):
        print('当前对象已创建, 占用内存地址 %s' % hex(id(self)))


a = Test()
print('当前对象的引用计数: ', sys.getrefcount(a))

引用计数增加

#   对象被创建
a = Test()
print('当前对象的引用计数: ', sys.getrefcount(a))  # 2
#   另外变量也指向当前对象
b = a
print('当前对象的引用计数: ', sys.getrefcount(a))  # 3
#   作为容器对象的一个元素
c = [a, b]
print('当前对象的引用计数: ', sys.getrefcount(a))  # 5

引用计数减少

#   变量被显式的销毁
# del a
print('当前对象的引用计数: ', sys.getrefcount(b))  # 4
#   对象的另外一个变量重新赋值 注意如果列表等存在该元素时并不会减少
b = 1000
print('当前对象的引用计数: ', sys.getrefcount(a))  # 3
#   从容器中移除
c.remove(a)
print('当前对象的引用计数: ', sys.getrefcount(a))  # 2

当引用计数为0时, 这个对象就会垃圾回收, 内存空间就被清空

垃圾收集-隔代回收机制

出现交叉引用(循环引用)就不能使用引用计数,

三个链表,零代链表上的对象(新创建的对象都加入到零代链表),引用数都是一,每增加一个指针,引用加一,随后
python会检测列表中的互相引用的对象,根据规则减掉其引用计数
gc模块
0号链表 出现 700个对象就会触发
1号链表 出现 10个对象就会触发
2号链表 出现 10个对象就会触发

import sys


class Test(object):
    def __init__(self):
        print('当前对象已创建, 占用内存地址 %s' % hex(id(self)))
        
    def __del__(self):  # 被回收之前会调用
        print('当前对象马上被系统gc回收 内存地址 %s' % hex(id(self)))
        

a = Test()
b = Test()
# 以下情况出现交叉引用
a.pro = b
b.pro = a

del a
print(sys.getrefcount(b))

import sys
import time
import gc


def timePlus():
    t = time.time()
    
    return '%s %.4f' % (time.strftime('%H:%M:%S', time.localtime(t)), t - int(t))


class Test(object):
    def __init__(self):
        print('当前对象已创建, 占用内存地址 %s' % hex(id(self)))
    
    def __del__(self):  # 被回收之前会调用
        print('当前对象马上被系统gc回收 内存地址 %s' % hex(id(self)))


while True:
    a = Test()
    b = Test()
    # 以下情况出现交叉引用
    a.pro = b
    b.pro = a
    
    del a
    del b
    
    print(gc.get_threshold(), timePlus())  # 打印隔代回收的阈值
    print(gc.get_count())  # 打印gc需要回收的对象的数量
    
    time.sleep(0.2)

gc.disable()  # 禁用隔代回收 一般不要禁用 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

CY3761

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值