前言
今天在做爬虫的时候,为了防止在填写字典key的时候,提前定义好了需要数据的字典格式,
在开发过程中遇到了数据结果全部相同的问题,在排查后终于发现问题所在,决定把这个小经验写下来。
问题
直接上例子代码:
a = {
"a": '',
'b': '',
'c': ''
}
def getres(reslist):
t = a
res = []
for each in reslist:
t['a'] = each[0]
t['b'] = each[1]
t['c'] = each[2]
print 't--',t
res.append(t)
return res
reslist = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
res = getres(reslist)
print 'res---', res
执行结果为:
t-- {'a': 1, 'c': 3, 'b': 2}
t-- {'a': 4, 'c': 6, 'b': 5}
t-- {'a': 7, 'c': 9, 'b': 8}
res--- [{'a': 7, 'c': 9, 'b': 8}, {'a': 7, 'c': 9, 'b': 8}, {'a': 7, 'c': 9, 'b': 8}]
从中发现虽然打印的时候t的值不同,但是在重新执行getres函数时候,由于字典内容的修改,导致列表中的对象内容也跟着修改了。
然后查找问题,对t重新进行复制,并打印ID
def getres(reslist):
t = a
res = []
for each in reslist:
t['a'] = each[0]
t['b'] = each[1]
t['c'] = each[2]
d = t
print 'd--',id(d)
print 't---',id(t)
res.append(d)
return res
输出结果发现他们在内存中的地址是一样,赋值 = 为# 浅拷贝: 只是引用对象,他们在内存中的地址是一样,d的值会随着t的改变而改变
d-- 41604056
t--- 41604056
d-- 41604056
t--- 41604056
d-- 41604056
t--- 41604056
res--- [{'a': 7, 'c': 9, 'b': 8}, {'a': 7, 'c': 9, 'b': 8}, {'a': 7, 'c': 9, 'b': 8}]
于是尝试使用字典的copy方法。copy函数也是浅拷贝:深拷贝父对象(一级目录),子对象(二级目录)不拷贝,还是引用
def getres(reslist):
t = a
res = []
for each in reslist:
t['a'] = each[0]
t['b'] = each[1]
t['c'] = each[2]
d = t.copy()
print 'd--',id(d)
print 't---',id(t)
res.append(d)
return res
输出结果为
d-- 44751512
t--- 44750072
d-- 44751224
t--- 44750072
d-- 44754680
t--- 44750072
res--- [{'a': 1, 'c': 3, 'b': 2}, {'a': 4, 'c': 6, 'b': 5}, {'a': 7, 'c': 9, 'b': 8}]
这里d copy t后的内存地址发生了改变,列表中的d不会随着t的改变而改变。