mat*_*anm 6 python garbage-collection weak-references
我有一种情况,只要存在第一个对象,我就想保持从一个对象到另一个对象的映射.我的第一个想法是使用WeakKeyDictionary.
import weakref
import gc
class M:
pass
w = weakref.WeakKeyDictionary()
m = M()
w[m] = some_other_object
del m
gc.collect()
print w.keys()
Run Code Online (Sandbox Code Playgroud)
在大多数情况下,这样做很好.但是,在some_other_object(或具有引用)m的M情况下,实例将不会被垃圾收集.(要查看示例,替换some_other_object用m)
当然,如果我将映射存储在对象本身上,当我删除它时会收集垃圾:
import weakref
import gc
class M:
pass
m = M()
m.circular_reference = m
r = weakref.ref(m)
del m
gc.collect()
print r
Run Code Online (Sandbox Code Playgroud)
我可以使用weakref模块实现第二个例子的结果(即没有变异m)吗?
换句话说,我可以使用weakref模块将对象映射到自身(或其他具有强引用的对象),并且只要有对象的其他引用,只将对象保留在内存中吗?
在这些示例中实际上并没有循环引用。你的圈子是这样的:
WeakKeyDict -> 值 -> 键 -> ...
因此,字典使值保持活动状态,这反过来又使键保持活动状态,并且通过不涉及强引用的单独机制,键指示字典保持值活动。由于此处没有正确的参考圆,因此 GC 永远不会检测到任何问题。(但是,您的第二个示例确实包含循环引用,这就是它的行为与第一个示例类似的原因)
我怀疑解决您问题的唯一方法是确保字典的值永远不会对字典中的任何键有强引用(直接或间接)。这与 srgerg 提出的类似,但您确实希望对键的引用是弱引用,而不是对所有值进行弱引用。例如:
import weakref
import gc
class M:
pass
w = weakref.WeakKeyDictionary()
key = M()
val = M()
val.keyRef = weakref.ref(val)
w[key] = val
print len(w) ## prints 1
del key
gc.collect()
print len(w) ## prints 0
Run Code Online (Sandbox Code Playgroud)
这样,总是有对值的强引用,但您要仔细控制对键的引用,以确定从 dict 中删除哪些内容。根据程序的复杂性,这可能会非常耗时,因为您需要手动跟踪对键的所有引用。
但如果您告诉我们更多有关具体问题的信息,也许我们可以提出一个更简单的解决方案。
| 归档时间: |
|
| 查看次数: |
815 次 |
| 最近记录: |