遇到问题:循环创建字典,传入列表会引起覆盖问题
构造数据集时,每个数据存储为字典的结构,类似于:
{
"123(data_id)": {
"detail":{....},
"QA":{.....}
}
}
每条数据都有一个data_id,并且包含一些细节信息detail、问答对QA。将每条数据构建好后插入list存储为json后发现,字典中的一些信息发生错误,最后一条数据的字典中部分信息覆盖了前面所有数据的该部分信息。
debug后发现错因:
引用问题:
如果在向列表中添加字典时,实际上是添加了字典对象的引用而不是副本,那么后续对字典对象的修改会影响到之前添加的内容。
举个简单例子,例如:
l = []
d1 = {
"a":1
}
l.append(d1)
d1['a'] = 10
print(l)
"""
[{"a": 10}]
"""
解决方法:
使用深拷贝(deepcopy)来创建字典的副本,或者确保在每次循环迭代时都创建一个全新的字典对象,并将其添加到列表中,以确保它们是独立的。
例如:
l = []
d1 = {
"a":1
}
l.append(d1)
d1['a'] = 10
d2 = {
"b": 2
}
l.append(copy.deepcopy(d2))
d2['b'] = 20
print(l)
"""
[{"a": 10}, {"b": 2}]
"""
浅拷贝copy & 深拷贝deepcopy
-
copy:copy函数是copy模块中的函数,用于创建一个浅拷贝(shallow copy)的对象。浅拷贝创建了一个新对象,该对象与原始对象共享内部对象的引用。这意味着对于可变对象,修改副本可能会影响原始对象。但对于不可变对象,修改副本不会影响原始对象。
-
deepcopy:deepcopy函数也是copy模块中的函数,用于创建一个深拷贝(deep copy)的对象。深拷贝创建了一个全新的对象,包括所有内部对象的副本,而不是仅仅共享引用。这意味着无论是可变对象还是不可变对象,修改副本都不会影响原始对象。
例如:
import copy
# 创建一个列表
original_list = [1, 2, [3, 4]]
# 浅拷贝
shallow_copy = copy.copy(original_list)
shallow_copy[2].append(5)
print(original_list) # 输出: [1, 2, [3, 4, 5]]
print(shallow_copy) # 输出: [1, 2, [3, 4, 5]]
# 深拷贝
deep_copy = copy.deepcopy(original_list)
deep_copy[2].append(6)
print(original_list) # 输出: [1, 2, [3, 4, 5]]
print(deep_copy) # 输出: [1, 2, [3, 4, 5, 6]]
总结
在深度学习构建数据集时,经常需要将每条数据存储为字典,依次传入列表,存储为json。注意往列表中传字典时,最好使用deepcopy后的字典传入