在做数据处理的时候, 碰到一个奇怪的现象.
for tuple in list.most_common():
dict['name'] = tuple[0]
dict['value'] = tuple[1]
d1.append(dict)
print(d1)
[{'name': '大兴', 'value': 32}, {'name': '大兴', 'value': 32}, {'name': '大兴', 'value': 32}, {'name': '大兴', 'value': 32}, {'name': '大兴', 'value': 32}, {'name': '大兴', 'value': 32}, {'name': '大兴', 'value': 32}]
发现d1这个列表里的每个元素都是一样的. 检查循环里的tuple 和 dict 一切正常.
循环里的d1 就不太正常...
for tuple in list.most_common():
dict['name'] = tuple[0]
dict['value'] = tuple[1]
d1.append(dict)
print(d1)
[{'name': '朝阳', 'value': 102}]
[{'name': '海淀', 'value': 65}, {'name': '海淀', 'value': 65}]
[{'name': '昌平', 'value': 53}, {'name': '昌平', 'value': 53}, {'name': '昌平', 'value': 53}]
[{'name': '丰台', 'value': 53}, {'name': '丰台', 'value': 53}, {'name': '丰台', 'value': 53}, {'name': '丰台', 'value': 53}]
[{'name': '西城', 'value': 48}, {'name': '西城', 'value': 48}, {'name': '西城', 'value': 48}, {'name': '西城', 'value': 48}, {'name': '西城', 'value': 48}]
部分数据是这样的. 发生了append的操作, 但列表里所有元素的值都一样. 为什么会这样?
几个小时后, 想到了一种可能性. 在append操作的时候, 传入的是一个引用, 导致后期dict变化, 前面元素的值也跟着变化. 解决方法是传入一个dict的copy, 传一个值, 而不是引用.
修改后的代码:
for tuple in list.most_common():
dict['name'] = tuple[0]
dict['value'] = tuple[1]
d = copy.copy(dict)
d1.append(d)
print(d1)
[{'name': '朝阳', 'value': 102}, {'name': '海淀', 'value': 65}, {'name': '丰台', 'value': 53}, {'name': '昌平', 'value': 53}, {'name': '西城', 'value': 48}, {'name': '通州', 'value': 36}, {'name': '大兴', 'value': 32}, {'name': '东城', 'value': 22}, {'name': '顺义', 'value': 18}, {'name': '石景山', 'value': 16}, {'name': 'NULL', 'value': 11}, {'name': '房山', 'value': 7}, {'name': '门头沟', 'value': 6}, {'name': '燕郊', 'value': 5}, {'name': '亦庄开发区', 'value': 3}]
ok, 确实是假想的那样, 传引用产生的问题, 加上一个拷贝语句就可以了. 可是之前也做过不少的利用append来构造字典数组的案例, 从没碰到过问题, 也没有添加过拷贝. 仔细观察之下, 发现我的 dict= {} 声明是放在for循环外的. 那这应该就是问题所在了.
再次修改后的代码:
for tuple in list.most_common():
# 把dict的定义放入 for 循环内
dict = {}
dict['name'] = tuple[0]
dict['value'] = tuple[1]
# d = copy.copy(dict)
d1.append(dict)
print(d1)
总结一下, 由于疏忽把dict= {}放在for循环外, 在append的时候, 一直添加的是同一个dict的引用, dict 内的值变化, 引起了列表内所有元素的变化.
在最后的修改里, 每一次循环, 都会新建一个空字典, 每次循环 dict 都是一个独立的值. 正确的做法也应该是这样的.
PS: 尝试了一下, Js的arr.push(obj) 也有同样的问题, 当然有良好编码习惯的人是不会碰到这种问题的.
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。