功能说明
Python使用引用计数、分代算法回收垃圾,引用计数操作方法:
对象被引用一次,其计数器+1
对象被del,其计数器-1
对象的引用计数为0时候会被回收
python的魔法方法__del__,类似java的finalize方法,会在对象被回收时执行。
实验验证
实验1: 删除仅引用一次的对象
步骤:
创建一个class,重写__del__方法,打印信息
创建该类实例,然后把它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
print(a)
NameError: name ‘a’ is not defined
结果分析:
调完del命令,__del__方法被执行,对象立即被删除(引用次数为0)
调完del命令后引用a被删除(其引用的对象不一定被删除,但是引用一定被删除)
实验2: 删除被多次引用的对象
步骤:
在上面那个用例的基础上,用多个引用引用A的对象
删除其中一个引用,观察对象是否被删除
预期:
删除一个引用,只是那个引用被删除了,但是对象不会被删除。
验证代码:
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>
c=<__main__.a object at>
name ‘a’ is not defined
A instance deleted
结果分析:
调完del命令删除a后,对象并没有被删除,通过其他引用b和c可以继续访问
对象在进程结束前被回收了,实际上不调用任何del,进程退出前A的实例都会被回收
推论:如果想回收A的实例,需要删除所有它的引用(引用次数降到0)
以上验证基于Python 3.7.7