问题:预期打印出来的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并没有拷贝这个对象,而只是拷贝了这个对象的引用
(1)直接赋值,传递对象的引用而已,原始列表改变,被赋值的b也会做相同的改变
(2)copy浅拷贝,只拷贝父对象,不会拷贝对象的内部的子对象,所以原始数据改变,子对象会改变
(3)copy深拷贝,包含对象里面的自对象的拷贝,所以原始对象的改变不会造成深拷贝里任何子元素的改变