列表添加字典类型元素的问题

最近在用Python进行爬虫解析时,遇到一个比较恼人的bug,归根结底是对Python中的深浅拷贝理解不够透彻。在这里记录下来以供将来查阅。

首先放一段代码:这段代码的功能是遍历列表中的元素对字典键值对中的值依次修改并将新的字典添加到dic_list这个列表中。

    dic_list = []
    lis = [1, 2, 3]
    dic = {}
    for ele in lis:
        dic["a"] = 1
        dic["b"] = 2
        dic["c"] = ele
        print dic
        dic_list.append(dic)
    print dic_list

输出结果为:

{'a': 1, 'c': 1, 'b': 2}
{'a': 1, 'c': 2, 'b': 2}
{'a': 1, 'c': 3, 'b': 2}
[{'a': 1, 'c': 3, 'b': 2}, {'a': 1, 'c': 3, 'b': 2}, {'a': 1, 'c': 3, 'b': 2}]

可以看到,每次输出的字典确实被改变了,但是添加新的字典后得到的字典列表却和预期的输出结果不一样,它包含的3个字典元素一模一样。这是怎么回事呢?

原因在于Python中的一切数据类型皆为object,不管是primitive types(int, float, str, bool)还是dict,list,tuple。在添加到列表中时,实际上添加的是指向该字典的引用。而Python中,字典是可变的,在字典被改变后,指向该字典的引用所对应的内容也会改变,所以得到的dic_list中的字典都是第3次循环得到的字典。可以通过添加两条语句得到我们想要的结果:

dic_list = []
lis = [1, 2, 3]
dic = {}
for ele in lis:
     dic["a"] = 1
     dic["b"] = 2
     dic["c"] = ele
     new_dic = dic.copy()
     dic_list.append(new_dic)
print dic_list

输出结果为:

[{'a': 1, 'c': 1, 'b': 2}, {'a': 1, 'c': 2, 'b': 2}, {'a': 1, 'c': 3, 'b': 2}]

其中,copy()方法用于返回字典的浅拷贝。至于深浅拷贝,等有时间再做整理~

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容