资讯专栏INFORMATION COLUMN

传的是值还是引用? 构造字典数组的一个bug

dockerclub / 2182人阅读

摘要:在做数据处理的时候碰到一个奇怪的现象大兴大兴大兴大兴大兴大兴大兴发现这个列表里的每个元素都是一样的检查循环里的和一切正常循环里的就不太正常朝阳海淀海淀昌平昌平昌平丰台丰台丰台丰台西城西城西城西城西城部分数据是这样的发生了的操作但列表里所有元

在做数据处理的时候, 碰到一个奇怪的现象.

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) 也有同样的问题, 当然有良好编码习惯的人是不会碰到这种问题的.

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/41747.html

相关文章

  • Javascript - 函数里是值还是引用

    摘要:说明一下里函数传的是值还是引用答案是都传。如果传入的参数是简单类型,如和,那么传入的就是值。如果是对象和数组,在函数里做的操作就会影响到函数外边。举几个栗子结语提问和纠错请留言。 说明一下 JavaScript里函数传的是值还是引用?答案是都传。如果传入的参数是简单类型,如String和Number,那么传入的就是值。但如果你传入的是Object和Array,那么就是引用。 这就意...

    JerryZou 评论0 收藏0
  • 深入理解javascript按值传递与按引用传递

    摘要:引用类型参数的传递与引用类型的复制一样,传递的是内存地址。指向一个新的地址,与不再指向同一个地址官方解释来一发中所有函数的参数都是按值传递的。总结很简单,函数参数都是按值传递都是栈内数据的拷贝。 基本类型与引用类型 值类型(基本类型):String,Number,Boolean,Null,Undefined。 引用类型:Array、Object、Function、Date等有多个值...

    陈江龙 评论0 收藏0
  • 深入理解javascript按值传递与按引用传递

    摘要:引用类型参数的传递与引用类型的复制一样,传递的是内存地址。指向一个新的地址,与不再指向同一个地址官方解释来一发中所有函数的参数都是按值传递的。总结很简单,函数参数都是按值传递都是栈内数据的拷贝。 基本类型与引用类型 值类型(基本类型):String,Number,Boolean,Null,Undefined。 引用类型:Array、Object、Function、Date等有多个值...

    hedzr 评论0 收藏0
  • js基础深入浅出

    摘要:当多个事件触发的时候,会把异步事件依次的放入里等同步事件执行完之后,再去队列里一个个执行拾遗常用方法总结面试的信心来源于过硬的基础参考高级程序设计你所不知道的深入浅出知识点思维导图经典实例总结那些剪不断理还乱的关系 持续不断更新。。。 基本类型和引用类型 vue props | Primitive vs Reference Types 基本类型和字面值之间的区别 基本类型和字面值相等,...

    phodal 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<