安全地迭代WeakKeyDictionary和WeakValueDictionary [英] Safely iterating over WeakKeyDictionary and WeakValueDictionary

查看:588
本文介绍了安全地迭代WeakKeyDictionary和WeakValueDictionary的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

$ c> WeakValueDictionary 有一个关于迭代这些容器的注释:

The documentation of Python 3.2's weakref module's WeakKeyDictionary and WeakValueDictionary have a note on iterating over these containers:


注意:注意:由于WeakKeyDictionary构建在Python字典之上,所以在迭代时不能改变大小。这可能难以确保WeakKeyDictionary,因为程序在迭代期间执行的操作可能导致字典中的项目由魔法消除(作为垃圾回收的副作用)。

Note: Caution: Because a WeakKeyDictionary is built on top of a Python dictionary, it must not change size when iterating over it. This can be difficult to ensure for a WeakKeyDictionary because actions performed by the program during iteration may cause items in the dictionary to vanish "by magic" (as a side effect of garbage collection).

这些容器的行为的规范似乎相当可怕。特别是当运行使用CPython的垃圾收集器的代码(使用包含循环的数据结构)或使用另一个Python实现(例如Jython)时,这听起来好像没有安全的方法来迭代这些集合。

That seems rather dire as a specification of these container's behavior. Especially when running code that uses CPython's garbage collector (when using data structures that contain cycle) or using another Python implementation (e.g. Jython), then it sounds as if there is no safe way of iterating over these collections.

如果垃圾收集器可能在程序中的任何一点清除引用,那么我如何安全地迭代这些集合?为CPython提供解决方案是我的首要任务,但我也对其他实现的问题感兴趣。

How can I safely iterate over these collections when the garbage collector may clear references at any point in my program? Having a solution for CPython is my priority but I'm interested about the issue on other implementations as well.

这可能是一个安全的方法来迭代WeakKeyDictionary? / p>

Is this maybe a safe way to iterate over a WeakKeyDictionary?

import weakref

d = weakref.WeakKeyDictionary()

...

for k, v in list(d.items()):
    ...


推荐答案

为了安全起见,你必须在某处保留参考。使用成语:

To be safe you have to keep a reference somewhere. Using the idiom:

for k,v in list(d.items()):

不是完全安全的,因为即使大部分时间都可以运行,在循环的最后一次迭代中,列表可能是垃圾回收,

is not completely safe because, even though it will work most of the time, during the last iteration of the loop the list may be garbage-collected.

正确的方法是:

items = list(d.items())
for k,v in items:
    #do stuff that doesn't have a chance of destroying "items"
del items

如果您使用 WeakKeyDictionary ,您可以简单地存储密钥,并存储值如果您使用 WeakValueDictionary

If you use a WeakKeyDictionary you could simply store the keys, and store values if you use WeakValueDictionary.

在旁注:在python2 .items() 已经返回列表。

On a side note: in python2 .items() already returns a list.

最终取决于你的意思是安全。如果您只是意味着迭代将正确进行(在所有元素上迭代一次),那么:

Ultimately it depends on what do you mean by "safe". If you simply mean that the iteration will proceed correctly(iterating once on all the elements), then:

for k,v in list(d.items()):

是安全的,因为字典上的迭代实际上是通过 list(d.items()),那么你只是在列表中迭代。

is safe, because the iteration over the dictionary is actually performed by list(d.items()), then you are only iterating over the list.

相反,意味着在迭代过程中,元素不应该从字典中消失,而是 -loop的的副作用,那么您必须保持强有力的参考,直到结束循环,这需要您在启动循环之前将列表存储在变量中。

If you, instead, mean that during the iteration elements should not "disappear" from the dictionary as side-effect of the for-loop, then you must keep a strong reference until the end of the loop, and this requires you to store the list in a variable before starting the loop.

这篇关于安全地迭代WeakKeyDictionary和WeakValueDictionary的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆