考虑以下示例代码
class A:
def __init__(self, i):
self.i = i
print("Initializing object {}".format(self.i))
def __del__(self):
print("Deleting object {}".format(self.i))
for i in [1, 2]:
a = A(i)
在循环中创建对象的目的是确保在创建新的A对象之前调用A的析构函数。但显然会发生以下情况:
初始化对象1
初始化对象2
删除对象1
删除对象2
为什么对象1的析构函数只在新对象初始化后才被调用?这是预期的行为吗?我知道for循环在python中没有自己的作用域。例如,在C ++中,在对象2的构造函数之前肯定会调用1的析构函数(至少如果在循环中声明了对象)。
在我的程序中,我想确保在创建新对象之前删除旧对象。除了在for循环结束时显式删除a
之外还有其他可能吗?
提前致谢。
答案 0 :(得分:11)
第二个对象的创建发生在名称反弹并且第一个对象被丢弃之前。
A
已实例化。a
受约束。A
已实例化。a
被反弹,第一个A
被处理掉。A
被处理掉。答案 1 :(得分:9)
在规划生命周期依赖关系时,您不能依赖垃圾收集器的实现细节。你需要以这种或那种方式明确地做到这一点。
上下文管理者会想到,例如:
from contextlib import contextmanager
@contextmanager
def deleting(obj):
try:
yield
finally:
del(obj)
class A:
def __init__(self, i):
self.i = i
print("Initializing object {}".format(self.i))
def __del__(self):
print("Deleting object {}".format(self.i))
for i in [1,2]:
with deleting(A(i)) as obj:
pass
print
for i in [1,2]:
a = A(i)
这会产生以下输出:
Initializing object 1
Deleting object 1
Initializing object 2
Deleting object 2
Initializing object 1
Initializing object 2
Deleting object 1
Deleting object 2
答案 2 :(得分:0)
假设您希望在循环退出时将对象定义为其最终值,请不要在for循环的 end 处明确删除对象,请在处执行此操作开始循环,如下所示:
class A:
def __init__(self, i):
self.i = i
print("Initializing object {}".format(self.i))
def __del__(self):
print("Deleting object {}".format(self.i))
for i in [1, 2, 3]:
a = None
a = A(i)
打印:
Initializing object 1
Deleting object 1
Initializing object 2
Deleting object 2
Initializing object 3
Deleting object 3
(注意:Ignatio对于它的工作原理是正确的,但是KennyTM也是正确的,为了使发生的事情变得更加明显,你应该让它在循环中至少进行三次。)