Python如何修改字典内嵌套列表的指定值?为何改单键列表会影响其他键?
问题根因
这个现象是Python可变对象的引用传递机制导致的,和字典本身的存储逻辑无关。
串值的底层逻辑
- 代码中
noneFillerList = [None] * 30会在内存中生成唯一的一份列表实体 - 循环给字典赋值时,执行
testDict[testDictKeys[x]] = noneFillerList,并没有给每个字典键创建专属的新列表,只是把这份唯一列表的内存地址,同时绑定到了XList、YList两个键上 - 这种绑定的效果等同于给同一个实体贴了两个不同标签:不管通过哪个标签访问,操作的都是同一份实体
- 因此执行
testDict['XList'][x] = 100时,本质是在修改所有键共享的那份列表实体,通过YList读取时自然会拿到修改后的值;如果打开YList的赋值注释,因为是对同一份实体的同一个位置二次写入254,最终两个键读取到的都是最后一次写入的254。
正确实现方案
核心规则:给字典的可变类型值(列表、字典等)赋值时,必须为每个键创建独立的对象实例,不能直接复用同一个可变对象的引用。
调整后的可运行代码:
testDictKeys = ['XList', 'YList', 'ZList'] testDict = dict.fromkeys(testDictKeys) # 为每个键创建独立的30长度空列表 for key in testDictKeys: testDict[key] = [None] * 30 # 每次循环生成全新的独立列表实例 # 跨键修改不会互相影响 for x in range(0, 29): testDict['XList'][x] = 100 testDict['YList'][x] = 254 print(testDict['XList'][0]) # 输出100 print(testDict['YList'][0]) # 输出254
常见避坑点
- 不要使用
dict.fromkeys(键列表, 可变默认值)的形式传可变对象做默认值,这种写法本质同样是把同一个可变对象的引用绑定到所有键上,必然出现改一个全字典串值的问题 - 判断两个字典值是否共享内存的简单方法:用
id(对象)函数查看内存地址,地址相同即为共享同一份实体。
内容的提问来源于stack exchange,提问作者user2224727
相关产品推荐
相关产品推荐

