【Python】list.append()字典在for循环中数据覆盖的分析与解决

时间:2021-10-16 00:05:49

问题:预期打印出来的list为:[{'num': 0}, {'num': 1}, {'num': 2}],结果为[{'num': 2}, {'num': 2}, {'num': 2}]

list=[]
dictionary={"num":""}
for i in range(3):
    dictionary["num"]=i
    list.append(d)
print(list)    #[{'num': 2}, {'num': 2}, {'num': 2}]

解决:将字典写在for循环中,得到预期的list[{'num': 0}, {'num': 1}, {'num': 2}]

list=[]
for i in range(3):
    dictionary={"num":""}
    dictionary["num"]=i
    list.append(d)
print(list)    #[{'num': 0}, {'num': 1}, {'num': 2}]

原因:

1.dictionary(字典)赋给list的是一个位置

2.dictionary定义在循环外,每次使用list.append(dictionary)赋给 list的都是相同的位置,即指向了同一块的地址;当在同一地址的dictionary的值已经改变了,所以list取到的之前位置的值改变了,表现出后面数据覆盖前面数据的表象

3.dictionary定义在循环内,相当于每一次循环生成一个dictionary,占用不同的位置存储值,所以可以赋给list不同元素不同的位置,获得不同的值。 

总结:

1.对于不能理解地址,可以通过在循环中print(id(dictionary)),将地址打印出来对比分析

2.在python中,对象赋值实际上是对象的引用。当创建一个对象,然后把它赋给另一个变量的时候,python并没有拷贝这个对象,而只是拷贝了这个对象的引用

3.关于Python中复制、浅拷贝和深拷贝的区别

    (1)直接赋值传递对象的引用而已原始列表改变,被赋值的b也会做相同的改变

    (2)copy浅拷贝,只拷贝父对象,不会拷贝对象的内部的子对象,所以原始数据改变,子对象会改变

    (3)copy深拷贝,包含对象里面的自对象的拷贝,所以原始对象的改变不会造成深拷贝里任何子元素的改变