在对象的第二次初始化时,为什么在__del__之前调用__init__?

sha*_*.dp 8 python oop

请考虑以下示例代码

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)
Run Code Online (Sandbox Code Playgroud)

在循环中创建对象旨在确保在创建新的A对象之前调用A的析构函数.但显然会发生以下情况:

初始化对象1

初始化对象2

删除对象1

删除对象2

为什么对象1的析构函数只在新对象初始化后才被调用?这是预期的行为吗?我知道for循环在python中没有自己的作用域.例如,在C++中,肯定会在对象2的构造函数之前调用1的析构函数(至少如果在循环中声明了对象).

在我的程序中,我想确保在创建新对象之前删除旧对象.除了a在for循环结束时显式删除之外还有其他可能吗?

提前致谢.

Ign*_*ams 11

第二个对象的创建发生在名称被反弹并且第一个对象被丢弃之前.

  1. 第一个A是实例化的.
  2. a 受约束.
  3. 第二个A是实例化的.
  4. a反弹,第一个A被处理掉.
  5. 程序结束,第二个A被处理掉.


Dav*_*nan 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)
Run Code Online (Sandbox Code Playgroud)

这会产生以下输出:

Initializing object 1
Deleting object 1
Initializing object 2
Deleting object 2

Initializing object 1
Initializing object 2
Deleting object 1
Deleting object 2
Run Code Online (Sandbox Code Playgroud)