python - 为什么下面的代码表现得如此奇怪? Python3.5 与 Python3.6

标签 python python-3.x language-lawyer

<分区>

正如标题所说,为什么下面的代码表现得如此奇怪?

a = {
    0: 0
}
b = []

for i in a:
    del a[i]
    a[i + 1] = 0
    b.append(i)

print(b)

在Python3.6中打印[0, 1, 2, 3, 4],而在Python3.5中打印[0, 1, 2, 3, 4, 5] , 6, 7]。为什么?

最佳答案

在这两种情况下,循环都不是无限的,原因很简单:您在字典上创建了一个迭代器。这只是一个内部知道哈希表大小并跟踪它到达的索引的对象。当遍历这个可迭代对象时,它会简单地检查散列表中的每个槽,看它是否已满,如果已满,则产生它,否则它会继续增加索引。

您的字典的大小永远不会增长,它总是有零个或一个元素,因此不会重新分配哈希表,迭代器会继续到哈希表的末尾。

此外:小整数散列自身:

>>> print(*map(hash, range(10)))
0 1 2 3 4 5 6 7 8 9

这意味着当您插入 i+1 == 1 时,它将在哈希表的槽 1 中结束,迭代器将在下一个循环。 2 等也会发生同样的情况。直到哈希码大到足以“包装”到哈希表的开头。迭代器索引不会回绕,因为它知道哈希表的大小。

Python3.5 和 python3.6 可能有不同的初始哈希表大小(请记住,在 python3.6 中,dict 类被重新实现以进行排序)。


显然,所有都是实现细节。没有语言保证迭代器会像这样运行,这只是实现的副作用。 future 的实现可能会检测到 dict 的任何更改并引发错误而不是继续。

关于python - 为什么下面的代码表现得如此奇怪? Python3.5 与 Python3.6,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55312183/

相关文章:

python - 使用IronPython2.7计算特征值和特征向量

python - Django jsonfield 在循环中保留旧对象值

Python套接字似乎无法建立连接

python - 为属性提供自定义 __str__ 表示

arrays - 数组可以有尾部填充吗?

java - 为什么在检查数组引用表达式是否为空之前评估 Java 数组索引表达式?

C++ header 单元导入语法

python - 在 pandas 中乘以浮点列需要太多时间

python - Py_INCREF/DECREF : When

python - 构建 python .whl 时排除目录?