这是在实际安全的迭代
WeakKeyDictionary,
WeakValueDictionary或
WeakSet在Python
2.7或Python
3.1+。他们引入了一个迭代保护措施,以防止弱引用回调从2010年以来的迭代过程中从底层dict或集合中删除引用,但是这些文档从未得到更新。
有了警惕,如果一个条目在迭代到达之前就死了,那么迭代将跳过该条目,但是不会导致segfault或RuntimeError或任何其他错误。无效条目将添加到挂起的删除列表中,并在以后处理。
这是警卫(尽管有评论,但不是线程安全的):
class _IterationGuard: # This context manager registers itself in the current iterators of the # weak container, such as to delay all removals until the context manager # exits. # This technique should be relatively thread-safe (since sets are). def __init__(self, weakcontainer): # Don't create cycles self.weakcontainer = ref(weakcontainer) def __enter__(self): w = self.weakcontainer() if w is not None: w._iterating.add(self) return self def __exit__(self, e, t, b): w = self.weakcontainer() if w is not None: s = w._iterating s.remove(self) if not s: w._commit_removals()
这是WeakKeyDictionary弱引用回调检查防护的地方:
def remove(k, selfref=ref(self)): self = selfref() if self is not None: if self._iterating: self._pending_removals.append(k) else: del self.data[k]
这是
WeakKeyDictionary.__iter__设置警卫的地方:
def keys(self): with _IterationGuard(self): for wr in self.data: obj = wr() if obj is not None: yield obj__iter__ = keys
在其他迭代器中使用相同的防护。
如果没有这个守卫,打电话
list(d.items())也不安全。GC遍历可能发生在
items迭代器内部,并在迭代过程中从dict中删除项目。(
list用C语言编写的事实不会提供任何保护。)
在2.6和更早的版本中,迭代WeakKeyDictionary或WeakValueDictionary的最安全方法是使用
items。
items会返回一个列表,并使用底层dict的
items方法,该方法通常不会被GC中断(主要是?)。在3.0的字典API的变化而变化如何
keys/
values/
items工作,这可能是为什么警卫被引入时,它是。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)