我需要一些帮助来理解为什么这段代码没有按预期工作。
如果想要更改字典的键但保留值,他/她可能会使用:
d[new_key] = d.pop[old_key]
我想修改所有键(并保留值)但下面的代码跳过某些行 - (“col2”) 保持不变。是不是因为字典是无序的,我一直在改变它的值?
我将如何在不创建新字典的情况下更改键并保留值?
import time
import pprint
name_dict = {"col1": 973, "col2": "1452 29th Street",
"col3": "Here is a value", "col4" : "Here is another value",
"col5" : "NULL", "col6": "Scottsdale",
"col7": "N/A", "col8" : "41.5946922",
"col9": "Building", "col10" : "Commercial"}
for k, v in name_dict.items():
print("This is the key: '%s' and this is the value '%s'\n" % (k, v) )
new_key = input("Please enter a new key: ")
name_dict[new_key] = name_dict.pop(k)
time.sleep(4)
pprint.pprint(name_dict)
原文由 Robert 发布,翻译遵循 CC BY-SA 4.0 许可协议
更改您正在迭代的对象从来都不是一个好主意。通常
dict
甚至在您尝试时抛出异常:但是,在您的情况下,您为每个删除的项目添加一个项目。这使它更加复杂。要了解正在发生的事情,您需要知道字典有点像稀疏表。例如像
{1: 1, 3: 3, 5: 5}
这样的字典可能看起来像这样(这在 Python 3.6 中发生了变化,对于 3.6 和更新版本,以下内容不再正确):这也是迭代的顺序。因此,在第一次迭代中,它将转到第二项(存储
1: 1
的位置)。假设您将密钥更改为2
并删除密钥1
字典将如下所示:但我们仍在第二行,因此下一次迭代将转到下一个“非空”条目,即
2: 1
。哎呀…将字符串作为键甚至更复杂,因为字符串哈希是随机的(在每个会话的基础上),所以字典中的顺序是不可预测的。
在 3.6 中,内部布局发生了一些变化,但这里发生了类似的事情。
假设你有这个循环:
初始布局是这样的:
第一个循环删除
1
但添加7
。因为字典在 3.6 中是有序的,所以插入了一个占位符,其中1
曾经是:这一直持续到您将
4
替换为10
。但是,当您将
5
替换为11
时,字典将需要增加其大小。然后会发生一些特别的事情:占位符被删除:因此,我们在上一次迭代中位于位置 5,现在我们更改第 6 行。但是第 6 行现在包含
11: 5
。哎呀…永远不要改变你正在迭代的对象:不要在迭代过程中弄乱键(值是可以的)!
您可以改为保留一个“翻译表”(不知道这是否违反了您的“不创建新字典”的要求,但您需要某种存储才能使您的代码正常工作)并在循环后进行重命名: