字典中替换关键字时的奇怪行为



我有一本字典,里面的键是单个字符。我想用它们的双重版本来替换大写字符。

例如,我有这样的结构:

x = 'AbCDEfGH'
a = dict(zip(list(x), range(len(x))))
print(a)

它创建了这个字典:

{'A': 0, 'b': 1, 'C': 2, 'D': 3, 'E': 4, 'f': 5, 'G': 6, 'H': 7}

值无关紧要,所以我只使用一些整数。我想要的是用双字符替换大写键,这样我就得到了:

{'AA': 0, 'b': 1, 'CC': 2, 'DD': 3, 'EE': 4, 'f': 5, 'GG': 6, 'HH': 7}

因此,我尝试了以下就地替换:

for k, v in a.items():
if k.isupper():
a[k+k] = a.pop(k)
print(a)

但奇怪的是,这导致了:

{'b': 1, 'E': 4, 'f': 5, 'G': 6, 'CCCCCCCCCCCCCCCC': 2, 'DDDDDDDDDDDDDDDD': 3, 'HHHHHHHHHHHHHHHH': 7, 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA': 0}

更奇怪的是,如果我将所有键都设置为大写:

y = 'ABCDEFGH'
a = dict(zip(list(y), range(len(y))))
for k, v in a.items():
if k.isupper():
a[k+k] = a.pop(k)
print(a)

它产生:

{'D': 3, 'E': 4, 'F': 5, 'CCCCCCCC': 2, 'GGGGGGGG': 6, 'HHHHHHHH': 7, 'AAAAAAAAAAAAAAAA': 0, 'BBBBBBBBBBBBBBBB': 1}
  • 发生了什么?我看到这些键的大小是2。但是,为什么
  • 我真的不在乎这些物品的顺序,但我看到有些甚至没有改变
  • 有没有其他方法可以像我打算的那样替换钥匙

.items()返回底层dict内容的实时视图。在迭代dict时对其进行突变会导致不可预测的效果,通常会导致某些密钥被处理多次(因此某些密钥会加倍(,而其他密钥则根本不被处理。如果dict在迭代过程中改变了大小,Python试图通过引发RuntimeError来保护您,但您的代码在检查时(当从迭代器请求下一项时(保持不变的大小,因此Python的廉价长度检查并不能拯救您。

最小的修复方法是使循环在items:的快照上运行

for k, v in tuple(a.items()):

一个更简单的解决方案是dict理解:

a = {k*2 if k.isupper() else k: v for k, v in a.items()}

这将在重新分配a之前使用双密钥构建一个全新的dict,因此不会出现突变问题。就这一点而言,你可以一下子构建a,只需执行以下操作:

a = {let*2 if let.isupper() else let: i for i, let in enumerate(x)}

无需list验证x(字符串已经按字符迭代(,enumerate可以为您的值编号,而根本不需要ziprangelen

最新更新