Python 垃圾回收机制

Python 中一切皆对象。因此,你所看到的一切变量,本质上都是对象的一个指针。
那么,怎么知道一个对象,是否永远都不能被调用了呢?
就是当这个对象的引用计数(指针数)为 0 的时候,说明这个对象永不可达,自然它也就成为了垃圾,需要被回收。

import os
import psutil

# 显示当前 python 程序占用的内存大小
def show_memory_info(hint):
    pid = os.getpid()
    p = psutil.Process(pid)
    
    info = p.memory_full_info()
    memory = info.uss / 1024. / 1024
    print('{} memory used: {} MB'.format(hint, memory))
    

def func():
    show_memory_info('initial')
    a = [i for i in range(10000000)]
    show_memory_info('after a created')

func()
show_memory_info('finished')
#该代码可在Ubuntu,Mac中运行,在Windows中运行会报错。

在上述代码中,会显示三次内存使用,第一次为初始时的,第二次的为运行func()函数,创建了a这个列表时,此时的数值会比第一次的大许多。第三次的func函数结束后,此时的数值应该是和第一次的差不多的,因为此时func函数中的a列表的作用域已经结束,所以他的内存也就自然而然的被自动释放了,而要是将a变量全局化的话

import os
import psutil

# 显示当前 python 程序占用的内存大小
def show_memory_info(hint):
    pid = os.getpid()
    p = psutil.Process(pid)
    
    info = p.memory_full_info()
    memory = info.uss / 1024. / 1024
    print('{} memory used: {} MB'.format(hint, memory))
    

def func():
    show_memory_info('initial')
    global a
    a = [i for i in range(10000000)]
    show_memory_info('after a created')

func()
show_memory_info('finished')

此时第三次输出的数值便会和第二边的是一样的。因为将a全局化之后,他所占用的内存便不会被释放。

计数查询

如果是想要查看a这个变量具体的计数次数的话,我们可以使用sys库中的getrefcount()方法

import sys

a = []
print(sys.getrefcount(a))

此时运行的话,打印出的结果应该是2,这是因为sys.getrefcount(a)也会算作一次计数,但是如果是多次使用sys.getrefcount(a)的话,他的次数不会累加

import sys

a = []
print(sys.getrefcount(a))
print(sys.getrefcount(a))

如这样的话,两次打印的结果都是2,不会叠加

循环引用

如果有两个对象,它们互相引用,并且不再被别的对象所引用,那么它们应该被垃圾回收吗?

def func():
    show_memory_info('initial')
    a = [i for i in range(10000000)]
    b = [i for i in range(10000000)]
    show_memory_info('after a, b created')
    a.append(b)
    b.append(a)

func()
show_memory_info('finished')

如这段代码中,a与b相互引用,我们运行代码会发现此时是不会自动释放内存的,这时就需要我们自行手动释放内存,这时我们需要用的gc库中的collect()方法。

import gc

def func():
    show_memory_info('initial')
    a = [i for i in range(10000000)]
    b = [i for i in range(10000000)]
    show_memory_info('after a, b created')
    a.append(b)
    b.append(a)

func()
gc.collect()
show_memory_info('finished')

这样便能解决循环引用不能自行释放内存的问题。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值