向元组列表追加元素时,为何元组内容会被修改?
为何元组列表中的字典会出现数据混叠?
我尝试创建一个由元组组成的列表,每个元组包含一个字符串(文件名)和一个字典(n-grams频率列表),预期每个元组对应独立文件的专属数据。
使用的代码如下:
documents = ['story.txt', 'great_expectations.txt'] outputs = [] for document in documents: doc_map = map_maker.make_map(document, 4, 10) list_tuple = (document, doc_map) # pprint.pprint(list_tuple) outputs.append(list_tuple) # pprint.pprint(outputs)
但执行后发现,不同文件对应的字典数据发生混叠,所有元组中的字典都包含了所有文件的n-grams条目。我原以为元组是不可变的,请问这一现象的原因是什么?
原因解析
- 元组的不可变性仅针对元组本身的元素引用,它存储的是字典的内存地址而非内容副本。也就是说,元组里的字典仍然是可变对象,其内容可以被修改。
- 核心问题出在
map_maker.make_map函数:这个函数大概率没有每次创建新的字典实例,而是复用了同一个全局或外部的字典对象。每次调用时只是往该字典追加当前文件的n-grams数据,并未生成独立字典。 - 因此所有元组里的字典都指向同一个内存地址,最终这个字典会累积所有文件的数据,看起来就像是发生了混叠。
验证与修复建议
- 验证问题:在循环内添加
print(id(doc_map)),如果两次输出的内存地址相同,即可确认是复用了同一个字典对象。 - 修复方案:
- 修改
make_map函数,确保每次调用时都初始化新字典(比如函数内部开头写current_dict = {},基于这个新字典统计n-grams)。 - 若无法修改
make_map,可在调用后复制字典:单层字典用doc_map.copy(),嵌套字典用import copy; copy.deepcopy(doc_map),再将副本存入元组。
- 修改
内容的提问来源于stack exchange,提问作者Thermobyte
相关产品推荐
相关产品推荐

