Python如何释放内存?

功能说明

Python使用引用计数、分代算法回收垃圾,引用计数操作方法:

  1. 对象被引用一次,其计数器+1
  2. 对象被del,其计数器-1
  3. 对象的引用计数为0时候会被回收

python的魔法方法__del__,类似java的finalize方法,会在对象被回收时执行。

实验验证

实验1: 删除仅引用一次的对象

步骤:

  1. 创建一个class,重写__del__方法,打印信息
  2. 创建该类实例,然后把它del掉,观察是否有回收消息

预期:
对象被回收。

验证代码:

import time
class A:
    def __del__(self):
        print("A instance deleted")
a = A()
del a

time.sleep(3)

print("sleep end")
print(a)

输出结果:

A instance deleted
sleep end
Traceback (most recent call last):
  File "/Users/wuhf/PycharmProjects/cookdata/cookdata/__init__.py", line 16, in <module>
    print(a)
NameError: name 'a' is not defined

结果分析:

  1. 调完del命令,__del__方法被执行,对象立即被删除(引用次数为0)
  2. 调完del命令后引用a被删除(其引用的对象不一定被删除,但是引用一定被删除)

实验2: 删除被多次引用的对象

步骤:

  1. 在上面那个用例的基础上,用多个引用引用A的对象
  2. 删除其中一个引用,观察对象是否被删除

预期:

删除一个引用,只是那个引用被删除了,但是对象不会被删除。

验证代码:

import time

class A:
    def __del__(self):
        print("A instance deleted")

a = A()

b=a
c=a

del a

time.sleep(3)

print("sleep end")
print("b=%s" % str(b))
print("c=%s" % str(c))

try:
    print("a=%s" % str(a))
except Exception as e:
    print(e)

输出结果:

sleep end
b=<__main__.A object at 0x101c154d0>
c=<__main__.A object at 0x101c154d0>
name 'a' is not defined
A instance deleted

结果分析:

  1. 调完del命令删除a后,对象并没有被删除,通过其他引用b和c可以继续访问
  2. 对象在进程结束前被回收了,实际上不调用任何del,进程退出前A的实例都会被回收
  3. 推论:如果想回收A的实例,需要删除所有它的引用(引用次数降到0)

以上验证基于Python 3.7.7

上一篇:[loj3329]有根树


下一篇:usOJ - 玩个三角形