对象绝不会自行销毁;然而,无法得到对象时,可能会被当做垃圾回收。
del语句是删除名称,而不是对象。
del语句可能会导致对象被当做垃圾回收,但是仅当删除了变量保存的是对象的最后一个引用,或者是无法得到对象的时候(比如两个对象相互引用)。还有就是重新绑定也可能导致对象的引用数量归零,导致对象被销毁。
在即将销毁实例时,Python解释器会调用__del__方法,给实例最后的机会,让其释放外部资源。自己编写的代码很少需要用到__del__代码,因为__del__很难用,费力不讨好。
在CPython中,垃圾回收的主要算法是引用计数。每个对象都会统计有多少引用指向了自己。当引用计数归零时,对象立即被销毁:CPython会在对象上调用__del__方法(如果定义了),然后释放分配给对象的内存。
CPython2.0增加了分代垃圾回收算法(隔代回收)。用于检测引用循环中涉及的对象组---如果一组对象之间是相互引用,即使再出色的引用方式也会导致组中的对象不可获取。
Python的其他实现有更复杂的垃圾回收程序,而且不依赖引用计数,这意味着引用数量归零时不会立即调用__del__方法,所以不要依赖__del__
示例,对象被销毁时的情形
import weakref # weakref:弱引用
s1 = {1, 2, 3}
s2 = s1 # s1和s2都是别名,指向集合{1,2,3}
def bye():
print('bye!')
ender = weakref.finalize(s1, bye) # 在s1的引用对象上注册bye回调,也就是当对象被回收后,会触发bye函数
print(ender.alive)
del s1
print(ender.alive) # 删除s1并没有触发bye函数,也就是对象没有被删除,只是删除了对象的引用s1
s2 = 'new' # 重新绑定了最后一个引用s2,让{1,2,3}无法获取了。此时对象被销毁了
print(ender.alive) # 验证被销毁
打印结果 True True bye! False
扩展知识点:
weakref模块支持对象的弱引用。正常的引用会增加对象的引用数,并避免它被垃圾回收。弱引用是一个不能避免对象被自动清理的对象句柄,不会影响其垃圾回收。