问题描述
问题的场景是在解析Excel文件出现的。下面是出现问题的一段代码:
# 此函数实现了解析Excel文件,并将文件中的每行数据以字典的形式返回(key为列名,value为对应的值)
def func():
...
yield result
# 将解析返回的每行数据追加到一个列表中
list = []
for dic in func():
list.append(dic)
print(list)
上面代码执行之后,输出的list中,发现所有元素的内容都是相同的,再去对比源文件,发现列表的元素都为Excel文件中最后一行内容。很明显,这肯定是不对的!
原因分析
出现这个问题之后,首先想到的就是逐步调试这段循环代码,同时观察dic的值和list中元素的值。
- 第一次循环时,list中对应的确实是Excel中第一行的内容,
- 第二次循环时,在dic已改变,但还没往list中追加第二个元素之前,发现第一次追加到list中的的元素的值已经发生了改变,而且改变之后的内容就和第二次循环时dic的内容相同。
到这里,就恍然大悟了,原来每次往列表中追加的都是这个字典的引用,而不是字典的内容,所以才会在每次循环时,出现只要dic的内容发生了变化,list中之前追加进去的dic也随着发生改变的情况。
解决方案
知道了这个原因,我们就知道在追加列表时,针对Excel的每行数据,都应该追加不同的引用。
那么具体的实现就是用到字典的copy()方法,如下:
list = []
for dic in func():
list.append(dic.copy())
copy()方法对字典dic进行了一个浅拷贝,也就是说对字典创建了一个新的引用。