免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
12下一页
最近访问板块 发新帖
查看: 13463 | 回复: 10

python 的list类型 append 数据时的问题 [复制链接]

论坛徽章:
0
发表于 2010-09-17 11:42 |显示全部楼层
python版本为2.5.4
测试问题如下:

>>> result=[]
>>> dict={'a': ''}
>>>
>>> dict['a']='f1'
>>> result.append(dict)
>>> result
[{'a': 'f1'}]
>>>
>>> dict['b']='f2'
>>> result.append(dict)
>>>
>>> result
[{'a': 'f1', 'b': 'f2'}, {'a': 'f1', 'b': 'f2'}]

在append第二个值时,第一个值同时也被更新了!


append常量时候就没问题:

>>> result=[]
>>> result.append({'a': 'f1'})
>>> result
[{'a': 'f1'}]
>>> result.append({'a': 'f1','b':'f2'})
>>> result
[{'a': 'f1'}, {'a': 'f1', 'b': 'f2'}]

有哪位高手知道原因吗?

论坛徽章:
0
发表于 2010-09-17 12:50 |显示全部楼层
变量名不要是dict,dict是内置类型名。

论坛徽章:
0
发表于 2010-09-17 20:28 |显示全部楼层
跟变量名没关系啊。

>>> result=[]
>>> hi_baby={'a': ''}
>>>
>>> hi_baby['a']='f1'
>>> result.append(hi_baby)
>>> result
[{'a': 'f1'}]
>>>
>>> hi_baby['b']='f2'
>>> result.append(hi_baby)
>>>
>>> result
[{'a': 'f1', 'b': 'f2'}, {'a': 'f1', 'b': 'f2'}]

论坛徽章:
0
发表于 2010-09-17 21:38 |显示全部楼层
本帖最后由 lunarwildgoose 于 2010-09-17 22:10 编辑

这应该是一个可变类型的引用问题。字典和列表都是可变类型,一般不要以列表或字典作为列表的元素。
>>> result=[]         #建立一个指向空列表实例的列表
>>> hi_baby={'a': ''} #建立一个字典引用,此时此字典对象含有一个关键字a
>>> hi_baby['a']='f1'   #修改此实例字典的a关键字的值
>>> result.append(hi_baby)  #把指向此字典对象的引用添加为result的元素
>>> result
[{'a': 'f1'}]
>>>
>>> hi_baby['b']='f2'           #对该字典对象增加一个值对
>>> result.append(hi_baby)  #把此字典对象的引用添加为result的新元素
>>>
>>> result                        #此时result有两个元素,都是指向hi_baby字典对象的引用
[{'a': 'f1', 'b': 'f2'}, {'a': 'f1', 'b': 'f2'}]   #故结果就是两个重复的hi_baby字典的值对

----------
hi_baby其实是运行环境中的一个字典对象的引用, hi_baby={'a': ''},这个式子中左值只是表示它是右值的引用,右值才真正的创建一个字典对象。
如果后面 hi_baby['b']='f2' 改成hi_baby={'a':hi_baby['a'],'b':'f2'},这样这里的hi_baby指向了新建立的字典对象,最后的result的前后两个元素就不一样了。

论坛徽章:
0
发表于 2010-09-18 00:06 |显示全部楼层
本帖最后由 a515200 于 2010-09-18 00:07 编辑

基础不牢。。在python核心编程第二版中这个问题不知被说了多少次了   看看名称命名空间locals()

论坛徽章:
0
发表于 2010-11-11 14:50 |显示全部楼层
  1. >>> import copy
  2. >>> Dict={'a': ''}
  3. >>> List=[]
  4. >>> List+=[Dict]
  5. >>> Dict['a']='bb'
  6. >>> List
  7. [{'a': 'bb'}]
  8. >>> List+=[copy.deepcopy(Dict)]
  9. >>> List
  10. [{'a': 'bb'}, {'a': 'bb'}]
  11. >>> Dict['a']='after deepcopy change'
  12. >>> List
  13. [{'a': 'after deepcopy change'}, {'a': 'bb'}]
  14. >>> del Dict
  15. >>> List
  16. [{'a': 'after deepcopy change'}, {'a': 'bb'}]
  17. >>>
复制代码
测试完成

论坛徽章:
0
发表于 2010-11-13 21:21 |显示全部楼层
dict的引用计数不为0时
你第二次对dict赋值,会把所有用到dict位置的数据都改变的

论坛徽章:
0
发表于 2010-11-13 21:57 |显示全部楼层
新学python的很多都被这个特征搞到疯掉

论坛徽章:
0
发表于 2010-11-14 11:57 |显示全部楼层
本帖最后由 donotblock 于 2010-11-14 12:06 编辑
  1. >>> result = []
  2. >>> dict = {'a':1}
  3. >>> result.append(dict)
  4. >>> dict['b']='second dict'
  5. >>> result.append(dict)
  6. >>> result
  7. [{'a': 1, 'b': 'second dict'}, {'a': 1, 'b': 'second dict'}]
  8. >>> id(dict)
  9. 3078914908L
  10. >>> id(result[0])
  11. 3078914908L
  12. >>> id(result[1])
  13. 3078914908L
复制代码
append并不做deepcopy,http://docs.python.org/library/stdtypes.html#typesseq 参见这里的Notes 2

论坛徽章:
0
发表于 2011-10-13 09:40 |显示全部楼层
回复 4# lunarwildgoose


    有时候书本的知识转化为编程的意识是要经过实践淘练的, 温故知新, 真不错, 学习了
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

DTCC2020中国数据库技术大会 限时8.5折

【架构革新 高效可控】2020年8月17日~19日第十一届中国数据库技术大会将在北京隆重召开。

大会设置2大主会场,20+技术专场,将邀请超百位行业专家,重点围绕数据架构、AI与大数据、传统企业数据库实践和国产开源数据库等内容展开分享和探讨,为广大数据领域从业人士提供一场年度盛会和交流平台。

http://dtcc.it168.com


大会官网>>
  

北京盛拓优讯信息技术有限公司. 版权所有 16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122
中国互联网协会会员  联系我们:huangweiwei@it168.com
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP