循环填充字典时列表值随迭代变更的原因咨询
字典值为列表时的引用异常问题
预期目标
想要构建一个键为整数、值为对应整数列表的字典,预期结果示例:
{0:[0], 1:[0,1], 2:[0,1,2], 3:[0,1,2,3] ...}
尝试的代码
dictfinal = {} List = [] for i in range(0,3): List.append(i) dictfinal[i] = List print(List) print(dictfinal)
实际输出结果
[0] {0: [0]} [0, 1] {0: [0, 1], 1: [0, 1]} [0, 1, 2] {0: [0, 1, 2], 1: [0, 1, 2], 2: [0, 1, 2]}
可以看到,每次迭代时已定义的字典键对应的值也会同步变更。
对比情况(值为整数时正常)
当将字典值改为整数时,问题消失:
dictfinal = {} List = [] for i in range(0,3): List.append(i) dictfinal.update({i:i}) print(List) print(dictfinal)
输出结果符合预期:
[0] {0: 0} [0, 1] {0: 0, 1: 1} [0, 1, 2] {0: 0, 1: 1, 2: 2}
问题原因
核心原因是Python里可变对象和不可变对象的引用逻辑不一样:
- 列表是可变对象:你只创建了一个
List列表对象,字典里所有键存的都是指向这个列表的「内存地址」(也就是引用)。每次List.append(i)都是在修改同一个列表,所以所有字典键对应的列表都会跟着变——它们本来就是同一个东西的不同别名而已。 - 整数是不可变对象:整数一旦创建就不能修改,当你给字典赋值
i:i时,每个键对应的都是独立的整数对象,不存在共享引用的问题,所以各键的值互不影响。
解决方法
要实现预期效果,需要确保每个字典键对应的是独立的列表对象,有几种常见写法:
方法1:每次循环新建列表
dictfinal = {} for i in range(0, 3): # 每次循环创建新的列表,避免共享引用 current_list = list(range(i+1)) dictfinal[i] = current_list print(current_list) print(dictfinal)
方法2:使用列表拷贝
如果需要基于之前的列表扩展,可以用切片或copy()方法创建新列表:
dictfinal = {} List = [] for i in range(0, 3): List.append(i) # 拷贝当前List的内容,生成新的列表对象 dictfinal[i] = List.copy() # 或者 List[:] print(List) print(dictfinal)
方法3:字典推导式(简洁写法)
dictfinal = {i: list(range(i+1)) for i in range(0, 3)} print(dictfinal)
以上方法的输出结果都会符合预期:{0: [0], 1: [0, 1], 2: [0, 1, 2]}
内容的提问来源于stack exchange,提问作者Matthew Rhys Dixon
相关产品推荐
相关产品推荐

