任何人都可以形容我为什么这段代码会打印'2 1 0完成'而不是预期输出'0 1 2完成'? 据我所知,我们在列表推导过程中创建了一些匿名变量,并且使用filo原理对列表理解无法结束进行垃圾收集。 但是,它们仍然在列表aa中引用,不是吗? 为什么第二个'del a'在这种情况下没有调用 del 魔法?
class A:
def __init__(self, name):
self.name = name
def __del__(self):
print self.name,
aa = [A(str(i)) for i in range(3)]
for a in aa:
del a
print 'done'
另外,高级问题。请查看http://codepad.org/niaUzGEy 为什么有5份,3份?这不是一份副本吗?为什么5或3?不知道,那就是为什么要问它;) 谢谢你的时间!
答案 0 :(得分:7)
您混淆了del
语句和__del__
方法。
del a
只是将名称a
与其引用的任何对象取消绑定。 aa
引用的列表未更改,因此对象都继续存在。
仅在对象的最后一次引用被销毁后调用__del__
方法。这可能是在致电__del__
之后,但通常不是。
您很少需要使用del
。重新绑定aa
然后释放它包含的所有对象会更加常见,如果没有其他引用,将自动调用它们的__del__
方法。
此外,您很少需要使用__del__
。对于大多数用途,Python对象的管理将自动处理清理。向类添加__del__
方法通常是一个坏主意,因为它可能会干扰垃圾收集器,所以相反自相矛盾__del__
使得程序更有可能泄漏内存。 Python也不能保证在程序退出时是否实际调用__del__
,如果确实如此,你可能会发现你不能再使用的全局变量,也不能保证只调用它一次(尽管你必须这样做)跳过篮球让它不止一次打电话。)
简而言之,如果可能,请避免使用__del__
。
答案 1 :(得分:3)
打印done 2 1 0
(CPython)。
您不会删除for循环中的列表元素。它们在退出时被删除。据我所知,__del__
的调用顺序是特定于实现的,所以它在另一个实现中可能有所不同(IronPython,Jython等)。