代码之家  ›  专栏  ›  技术社区  ›  Arlaharen

在“德鲁”中关闭/处理对象真的可以吗?

  •  7
  • Arlaharen  · 技术社区  · 15 年前

    我一直在思考如何用Python编写类。更具体地说,如何实现构造函数以及如何销毁对象。我不想依靠cpython的引用计数来进行对象清理。这基本上告诉我应该使用WITH语句来管理对象的生命周期,并且我需要一个显式的close/dispose方法(可以从 __exit__ 如果对象也是上下文管理器)。

    class Foo(object):
        def __init__(self):
            pass
        def close(self):
            pass
    

    现在,如果我的所有对象都以这种方式运行,并且我的所有代码都使用WITH语句或显式调用 close() (或) dispose() )我真的不认为我需要输入任何代码 __del__ . 我们真的要用吗 埃尔德勒斯 处理我们的物品?

    3 回复  |  直到 15 年前
        1
  •  13
  •   Lennart Regebro    15 年前

    简短回答:不。

    长答案:使用 __del__ 这很棘手,主要是因为它不能保证被调用。这意味着你不能做那些必须做的事情。这反过来意味着 埃尔德勒斯 基本上只能用于迟早会发生的清理,比如清理进程退出时将被清理的资源,所以 埃尔德勒斯 不会接到电话。当然,这些通常也是Python为您所做的相同的事情。所以有点 埃尔德勒斯 无用的。

    也, 埃尔德勒斯 当python垃圾收集时调用,而您不想等待pythons垃圾收集,这意味着您不能使用 埃尔德勒斯 不管怎样。

    所以,不要使用 埃尔德勒斯 . 使用 __enter__/__exit__ 相反。

    仅供参考:下面是一个非循环情况的示例,其中未调用析构函数:

    class A(object):
        def __init__(self):
            print('Constructing A')
    
        def __del__(self):
            print('Destructing A')
    
    class B(object):
        a = A()
    

    好的,这是一个类属性。显然这是一个特例。但这只是为了证明这一点 埃尔德勒斯 打电话不容易。我很肯定我看到过更多的非循环情况 埃尔德勒斯 不叫。

        2
  •  8
  •   ars    15 年前

    不一定。当您有循环引用时,会遇到问题。EliBendersky在他的博客中很好地解释了这一点:

        3
  •  0
  •   rob    15 年前

    如果您确定不会进入循环引用,则使用 __del__ 这样就可以了:一旦引用计数变为零,cpython vm将调用该方法并销毁对象。

    如果您计划使用循环引用,请仔细考虑,并检查弱引用是否有帮助;在许多情况下,循环引用是不良设计的第一个症状。

    如果您无法控制对象的使用方式,请使用 埃尔德勒斯 可能不安全。

    如果你打算用JPython或者Ironpython, 埃尔德勒斯 完全不可靠,因为最终的对象销毁将在垃圾收集时发生,这是您无法控制的。

    总之,在我看来, 埃尔德勒斯 通常是完全安全和良好的;但是,在许多情况下,最好退后一步,尝试从不同的角度看待问题;正确使用Try/Except和With Context可能是一种更为蟒蛇式的解决方案。