根据我的理解,Python 3不保证何时释放对象的内存,只要至少有一个非弱引用指向对象,它就不会被释放。
该语言是否对弱引用做出任何其他保证?特别是,假设我创建了一个指向某个对象的weakref wr
。假设稍后,对该对象的所有非弱引用都已被破坏。是否保证当时wr
会评估为无,或者它仍然可以评估原始对象一段时间?
除语言保证外,围绕weakref还有任何有趣的实现行为吗?
答案 0 :(得分:1)
只有在GC启动后,才会销毁弱引用的对象。由于这是非确定性的,因此无法保证在所有强引用都被删除后它将被销毁。
来自docs:
...当对指示物的唯一剩余引用很弱时 引用,垃圾收集可以自由地销毁指示物和 重用它的记忆力。
操作性短语“可以自由地摧毁指示物” - 它可能不会立即发生。
答案 1 :(得分:1)
不,Python不保证何时实际收集对象并且weakref将返回None
。它可能立即发生(它通常在CPython中,它使用引用计数加循环引用垃圾收集器,但在不使用引用计数的其他Python实现中更少见。)它也可以延迟一些原因 - 不使用CPython(或使用不使用引用计数的CPython版本),或使用引用计数但是当对象参与引用循环时。
答案 2 :(得分:1)
weakref要么为您提供有效对象(来自Python的POV),要么为None。此时实际取消分配对象(导致weakref转到None)是未定义的,除了不能从任何其他活动对象对该对象进行任何非弱引用。您在CPython中观察到的引用计数行为无法保证。
答案 3 :(得分:0)
因为似乎所有弱的引用都是连贯地发布的(根据Guido的帖子)。您可以做的一件事是在每个位置使用一个弱引用,否则您将生成一个新的弱引用(因为单个引用必须与使用它的所有人看起来相同)。
在这里,您将失去所有不同引用引用的良好回调机制,但您可以通过继承weakref.ref并添加某种注册方案来恢复它们。您还需要一些方法来定位weakref的单个实例。将它与要引用的实例打包在一起,并创建一个帮助方法来获取它或创建它(注意线程安全问题,如果你不想要锁也使用默认的getattr)。或者你可以做一个单例来找到它们(使用第一种方法......)。
弱点中的连贯消失似乎应该保证为了理智的备忘录方案,但是使用单个弱点应该可以工作,虽然代价是以你需要的保证重新实现解释器的weakref方案。
你实际上可以使用.__weakref__
属性,其中weakrefs显示在解释器中的实例上,并使用辅助函数方法。