猿问

我不了解python __del__的行为

有人可以解释为什么以下代码会如此行为:


import types


class Dummy():

    def __init__(self, name):

        self.name = name

    def __del__(self):

        print "delete",self.name


d1 = Dummy("d1")

del d1

d1 = None

print "after d1"


d2 = Dummy("d2")

def func(self):

    print "func called"

d2.func = types.MethodType(func, d2)

d2.func()

del d2

d2 = None

print "after d2"


d3 = Dummy("d3")

def func(self):

    print "func called"

d3.func = types.MethodType(func, d3)

d3.func()

d3.func = None

del d3

d3 = None

print "after d3"

输出(请注意,永远不会调用d2的析构函数)是(python 2.7)


delete d1

after d1

func called

after d2

func called

delete d3

after d3

有没有一种方法可以“修复”代码,以便在不删除添加的方法的情况下调用析构函数?我的意思是,放置d2.func = None的最佳位置将在析构函数中!


谢谢


[edit]根据前几个答案,我想澄清一下,我并不是在问using的优点(或缺点)__del__。我试图创建最短的函数来证明我认为是非直觉的行为。我假设已经创建了循环引用,但是我不确定为什么。如果可能的话,我想知道如何避免使用循环引用。


白猪掌柜的
浏览 519回答 3
3回答

有只小跳蛙

您不能假设__del__会被调用-这不是一个希望自动分配资源的地方。如果要确保释放(非内存)资源,则应制作一个release()或类似的方法,然后显式调用它(或在Thanatos在下面的注释中指出的上下文管理器中使用它)。至少您应该非常仔细地阅读__del__ 文档,然后您可能不应该尝试使用__del__。(另请参阅gc.garbage 文档,了解有关的其他不良信息__del__)

温温酱

del 不打电话 __del__del以您使用的方式删除局部变量。__del__销毁对象时调用。Python作为一种语言无法保证何时销毁对象。CPython是Python最常见的实现,它使用引用计数。因此,del通常会按您期望的那样工作。但是,如果您有参考循环,则该功能将无效。d3 -> d3.func -> d3Python不会检测到该错误,因此不会立即对其进行清理。而且它不只是参考周期。如果引发异常,则可能仍要调用析构函数。但是,Python通常会保留局部变量作为其回溯的一部分。解决方案不取决于__del__方法。而是使用上下文管理器。class Dummy:   def __enter__(self):       return self   def __exit__(self, type, value, traceback):       print "Destroying", selfwith Dummy() as dummy:    # Do whatever you want with dummy in here# __exit__ will be called before you get here这样可以保证正常工作,您甚至可以检查参数以查看是否正在处理异常并在这种情况下执行其他操作。
随时随地看视频慕课网APP

相关分类

Python
我要回答