在互联网上浏览(here)我发现使用__del__
方法为垃圾收集器收集对象存在一些问题。
我的疑问很简单:为什么?
根据文件:
具有
__del__()
方法且属于引用循环的对象会导致整个引用循环无法收集,包括不一定在循环中但只能从其中访问的对象。 Python不会自动收集这样的循环,因为一般来说,Python无法猜测运行__del__()
方法的安全顺序。
为什么__del__
方法有问题?实现它的对象和不实现它的对象有什么区别?它只会破坏一个实例。
答案 0 :(得分:3)
__del__
不会销毁实例,一旦其引用计数达到零,它就会被python运行时自动销毁。 __del__
允许您挂钩该进程并执行其他操作,例如释放与该对象关联的外部资源。
危险在于附加操作甚至可以复活对象 - 例如,通过将其存储到全局容器中。在这种情况下,销毁被有效取消(直到下一次对象的引用计数降至零)。正是这种情况导致仅存在__del__
以将对象排除在由循环断路器(也称为垃圾收集器)管理的对象之外。如果收集器在循环中的所有对象上调用__del__
,并且其中一个决定复活对象,则需要复活整个循环 - 这是不可能的,因为其他循环成员的__del__
方法具有已被调用,可能对其对象造成永久性损坏(例如,通过释放外部资源,如上所述)。
如果您只需要通知对象的销毁,请使用weakref.ref
。如果您的对象与需要释放的外部资源相关联,请实现close
方法和/或上下文管理器接口。使用__del__
几乎没有合理的理由。