Python 怎么知道有人在遍历字典?

如果有人尝试:

my_dict = {1: 1}
for key in my_dict:
    my_dict.pop(key)

一个人会得到:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
RuntimeError: dictionary changed size during iteration

Python 会抛出错误,因为您在循环时更改了 dict 的大小。

Python 如何知道发生了这种情况,并且可以通过编程方式覆盖此功能以便代码运行吗?

在有人问“我为什么要这样做”这个不可避免的问题之前:我不想。我在问一个问题。这叫做好奇心。

例如:

假设我有一个包含 5 个项目的字典。上面的代码应该简单地删除字典中的所有项目!

回答

如果您在 Python 源代码中搜索“字典在迭代期间改变大小”,您会发现Objects/dictobject.c

static PyObject*
dictiter_iternextkey(dictiterobject *di)
{
/* ... omitted ... */
if (di->di_used != d->ma_used) {
PyErr_SetString(PyExc_RuntimeError,
"dictionary changed size during iteration");
di->di_used = -1; /* Make this state sticky */
return NULL;
}

ma_used字段只是字典中的项目数,如 中所述dictobject.h

/* Number of items in the dictionary */
Py_ssize_t ma_used;

并且di_used只是迭代器创建时该值的副本。

您不能以编程方式更改此设置,至少不能以任何合理的方式进行更改(我们不要使用 monkey-patch dict)。如果愿意,您可以创建自己的字典类型,并定义自己的行为不同的迭代器。

Python 这样做的原因是因为当您迭代一个正在更改的哈希表时,很难弄清楚“正确”的事情是什么。

编写你自己的哈希表实现是一个很好的练习,你会很快发现问题......当你在哈希表中插入或删除条目时,它可能会改变其他条目的顺序——迭代器是否可以接受跳过条目,或两次返回相同的条目?可能不是。你能创建一个提供你想要的迭代行为的数据结构吗?是的,但它很复杂,并且执行此操作的哈希表在其他情况下可能会表现更差。


以上是Python 怎么知道有人在遍历字典?的全部内容。
THE END
分享
二维码
< <上一篇
下一篇>>