功能说明
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 <module>
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 0x101c154d0>
c=<__main__.A object at 0x101c154d0>
name 'a' is not defined
A instance deleted
结果分析:
- 调完del命令删除a后,对象并没有被删除,通过其他引用b和c可以继续访问
- 对象在进程结束前被回收了,实际上不调用任何del,进程退出前A的实例都会被回收
- 推论:如果想回收A的实例,需要删除所有它的引用(引用次数降到0)
以上验证基于Python 3.7.7