为什么我不能在迭代另一个字典时修改一个字典(get changed size error)?

2024-04-26 18:34:23 发布

您现在位置:Python中文网/ 问答频道 /正文

我很困惑,为什么修改一个使用另一个字典创建的字典会导致运行时错误:字典在迭代过程中改变了大小:

def test(somedict):
    new = somedict
    for k,v in somedict.iteritems():
        new['test'] = new.pop(k)
    return new

>>>test(data)
Traceback (most recent call last):
  File "<pyshell#12>", line 1, in <module>
    test(data[0])
  File "<pyshell#10>", line 3, in test
    for k,v in somedict.iteritems():
RuntimeError: dictionary changed size during iteration    

用例:我试图使用查找表替换字典副本中的所有键,并注意到我无法从没有迭代的新字典中弹出()键。你知道吗

我意识到收到():

new = somedict.copy()

解决问题。但我不明白为什么这在python中是非法的。你知道吗

有人能解释一下new=somedict和new=收到()? 赋值变量并不意味着派生新赋值的数据在修改子变量时也会被修改,至少我是这么想的。你知道吗


Tags: intestnewfordata字典过程def
3条回答
def test(somedict):
    new = somedict
    for k,v in somedict.iteritems():
        new['test'] = new.pop(k)
    return new

相当于:

def test(somedict):
    for k,v in somedict.iteritems():
        somedict['test'] = somedict.pop(k)
    return somedict

因为语句new = somedict意味着newsomedict是同一个字典

在循环中,您迭代somedict的键/值对,并且弹出somedict的元素,因此字典的大小发生了变化,从而导致

RuntimeError: dictionary changed size during iteration:

通过使用new = somedict.copy(),您可以创建字典的新副本,因此修改new不会修改somedict,您就解决了问题。你知道吗

简而言之,查找引用语义和值语义来理解Python的行为。你知道吗

这是因为new = somedict实际上并不意味着它们是内存中两个独立的对象。它们实际上是相同的物体。你知道吗

但是,当您使用.copy()时,您现在正在内存中创建一个新对象,允许您对其进行操作。你知道吗

str_MemoryID = "Object {0:10} memory location is: {1}"
str_Contents = "Object {0:10} contents are: {1}"

test = {"one":1, "two":2}
new = test
new_copy = test.copy()

# printing the memory ID of the objects
print(str_MemoryID.format("test", id(test)))
print(str_MemoryID.format("new", id(new)))
print(str_MemoryID.format("new_copy", id(new_copy)))

print("\n")

# print the contents of the dictionaries

print(str_Contents.format("test", test))
print(str_Contents.format("new", new))
print(str_Contents.format("new_copy", new_copy))

print("\n")

# make a change to the "new" dictionary and let's see what happens
new['new_item'] = 3

print(str_Contents.format("test", test))
print(str_Contents.format("new", new))
print(str_Contents.format("new_copy", new_copy))

print("\n")

# make a change to the "new_copy" dictionary and let's see what happens
new_copy.popitem()

print(str_Contents.format("test", test))
print(str_Contents.format("new", new))
print(str_Contents.format("new_copy", new_copy))

提供以下输出:

Object test       memory location is: 8606920
Object new        memory location is: 8606920
Object new_copy   memory location is: 8606856


Object test       contents are: {'one': 1, 'two': 2}
Object new        contents are: {'one': 1, 'two': 2}
Object new_copy   contents are: {'one': 1, 'two': 2}


Object test       contents are: {'one': 1, 'new_item': 3, 'two': 2}
Object new        contents are: {'one': 1, 'new_item': 3, 'two': 2}
Object new_copy   contents are: {'one': 1, 'two': 2}


Object test       contents are: {'one': 1, 'new_item': 3, 'two': 2}
Object new        contents are: {'one': 1, 'new_item': 3, 'two': 2}
Object new_copy   contents are: {'two': 2}   

相关问题 更多 >