可以weakref不计算为None,即使没有非弱引用指向对象



据我所知,Python3不会保证对象的内存何时释放,只是只要至少有一个非弱引用指向对象,它就不会释放。

该语言是否对弱引用做出了任何其他保证?特别是,假设我创建了一个指向某个对象的weakref wr。假设稍后某个时间,对该对象的所有非弱引用都已被销毁。是否保证wr在那个时候会求值为None,或者它可能在一段时间内仍然求值为原始对象?

除了语言保证之外,weakref还有什么有趣的实现行为吗?

只有GC启动后,弱引用对象才会被销毁。由于这是不确定的,因此不能保证在删除所有强引用后立即销毁。

来自文档:

当对引用对象的唯一剩余引用为弱引用时引用,垃圾回收可以自由销毁引用和将其内存重新用于其他用途。

其中最重要的一句话是"可以自由地摧毁参照物"——这可能不会立即发生。

不,Python不会保证对象何时被实际收集,weakref将返回None。它可能会立即发生(通常是在CPython中,它使用引用计数加上循环引用垃圾收集器,但在其他不使用refcounting的Python实现中很少发生。)它也可能由于多种原因而延迟——当不使用CPython(或使用不使用refcount的CPython版本)时,或者当使用refcounting但对象参与引用循环时。

weakref要么为您提供一个有效的对象(来自Python的POV),要么为None。在哪一点上,对象实际上被解除分配(导致weakref变为None)是未定义的,除了不能有任何其他活动对象对该对象的非弱引用。不能保证您在CPython中观察到的引用计数行为。

因为似乎不能保证所有弱引用都能一致发布(根据Guido的帖子)。你可以做的一件事是在每个位置使用一个弱引用,否则你会生成一个新的弱引用(因为这个弱引用对所有使用它的人来说都必须是一样的)。

在这里,您将失去对引用的所有不同引用的良好回调机制,但您可以通过子类化weakref.ref并添加某种注册方案来恢复它们。您还需要某种方法来定位weakref的单个实例。将它与要引用的实例打包,并制作一个helper方法来获取它或创建它(注意线程安全问题,如果您不想要锁,请使用getattr作为默认值)。或者,你可以制作一个单例来找到它们(使用第一种方法…)

为了合理的记忆方案,weakref中的连贯性不明显似乎应该得到保证,但使用单个weakref应该有效,尽管代价是在您需要的保证下重新实现解释器的weakref方案。

实际上,您可以使用.__weakref__属性,其中weakrefs显示在解释器中的实例上,并使用helper函数方法。

最新更新