为了账号安全,请及时绑定邮箱和手机立即绑定

我不了解python __del__的行为

我不了解python __del__的行为

白猪掌柜的 2019-10-21 10:37:41
有人可以解释为什么以下代码会如此行为:import typesclass Dummy():    def __init__(self, name):        self.name = name    def __del__(self):        print "delete",self.named1 = Dummy("d1")del d1d1 = Noneprint "after d1"d2 = Dummy("d2")def func(self):    print "func called"d2.func = types.MethodType(func, d2)d2.func()del d2d2 = Noneprint "after d2"d3 = Dummy("d3")def func(self):    print "func called"d3.func = types.MethodType(func, d3)d3.func()d3.func = Nonedel d3d3 = Noneprint "after d3"输出(请注意,永远不会调用d2的析构函数)是(python 2.7)delete d1after d1func calledafter d2func calleddelete d3after d3有没有一种方法可以“修复”代码,以便在不删除添加的方法的情况下调用析构函数?我的意思是,放置d2.func = None的最佳位置将在析构函数中!谢谢[edit]根据前几个答案,我想澄清一下,我并不是在问using的优点(或缺点)__del__。我试图创建最短的函数来证明我认为是非直觉的行为。我假设已经创建了循环引用,但是我不确定为什么。如果可能的话,我想知道如何避免使用循环引用。
查看完整描述

3 回答

?
有只小跳蛙

TA贡献1824条经验 获得超8个赞

您不能假设__del__会被调用-这不是一个希望自动分配资源的地方。如果要确保释放(非内存)资源,则应制作一个release()或类似的方法,然后显式调用它(或在Thanatos在下面的注释中指出的上下文管理器中使用它)。


至少您应该非常仔细地阅读__del__ 文档,然后您可能不应该尝试使用__del__。(另请参阅gc.garbage 文档,了解有关的其他不良信息__del__)


查看完整回答
反对 回复 2019-10-21
?
温温酱

TA贡献1752条经验 获得超4个赞

del 不打电话 __del__


del以您使用的方式删除局部变量。__del__销毁对象时调用。Python作为一种语言无法保证何时销毁对象。


CPython是Python最常见的实现,它使用引用计数。因此,del通常会按您期望的那样工作。但是,如果您有参考循环,则该功能将无效。


d3 -> d3.func -> d3

Python不会检测到该错误,因此不会立即对其进行清理。而且它不只是参考周期。如果引发异常,则可能仍要调用析构函数。但是,Python通常会保留局部变量作为其回溯的一部分。


解决方案不取决于__del__方法。而是使用上下文管理器。


class Dummy:

   def __enter__(self):

       return self


   def __exit__(self, type, value, traceback):

       print "Destroying", self


with Dummy() as dummy:

    # Do whatever you want with dummy in here

# __exit__ will be called before you get here

这样可以保证正常工作,您甚至可以检查参数以查看是否正在处理异常并在这种情况下执行其他操作。


查看完整回答
反对 回复 2019-10-21
  • 3 回答
  • 0 关注
  • 518 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信