嵌套字典添加文件路径时出现全域追加异常,求排查解决
问题描述
我需要构建文件目录,创建了如下结构的嵌套字典logtype_files_library:
{'logtype16777217': {'Table_AmfSetID.csv': [], 'Table_QCI.csv': [], 'Table_body.csv': [], 'Table_head.csv': [], 'Table_AmfPointer.csv': [], 'Table_AmfRegionID.csv': []}, 'logtype16777218': {'Table_AmfSetID.csv': [], 'Table_QCI.csv': [], 'Table_body.csv': [], 'Table_head.csv': [], 'Table_AmfPointer.csv': [], 'Table_AmfRegionID.csv': []}, ...}
filenames为文件路径列表,示例如下:
['/mnt/c/Users/d00858421/Downloads/csv-N800/0010_logtype16777217_File.csv', '/mnt/c/Users/d00858421/Downloads/csv-N800/0010_logtype16777217_Table_AmfPointer.csv', '/mnt/c/Users/d00858421/Downloads/csv-N800/0010_logtype16777217_Table_AmfRegionID.csv', ...]
我使用如下循环尝试将每个文件路径添加到对应logtype下的对应table列表中:
for file in filenames: file_logtype = [i for i in file.split('/')[-1].split('_') if i.startswith('logtype')][0] table_type = '_'.join(file.split('/')[-1].split('_')[2:]) logtype_files_library[file_logtype][table_type].append(file)
但运行异常:所有列表都被追加了所有文件路径,而非仅对应列表。请问问题出在哪里?
问题原因
你创建logtype_files_library时,大概率是先定义了一个包含空列表的模板字典,再通过复制这个模板生成每个logtype对应的子字典(比如用dict.copy()或直接赋值)。由于列表是可变对象,这种浅拷贝会导致所有logtype下的同名table列表引用的是同一个内存对象。当你对任意一个列表执行append操作时,所有指向该对象的列表都会同步变化,最终表现为所有列表都被添加了所有文件路径。
比如错误的创建方式可能是这样:
# 错误示例:所有子字典复用同一个列表对象 table_template = { 'Table_AmfSetID.csv': [], 'Table_QCI.csv': [], # ...其他表 } logtype_files_library = { 'logtype16777217': table_template, 'logtype16777218': table_template, # ...其他logtype }
解决方法
需要确保每个logtype对应的子字典里的列表都是独立的新对象,可以通过以下三种方式实现:
方式1:为每个logtype单独创建子字典
logtype_files_library = { 'logtype16777217': { 'Table_AmfSetID.csv': [], 'Table_QCI.csv': [], 'Table_body.csv': [], 'Table_head.csv': [], 'Table_AmfPointer.csv': [], 'Table_AmfRegionID.csv': [] }, 'logtype16777218': { 'Table_AmfSetID.csv': [], 'Table_QCI.csv': [], 'Table_body.csv': [], 'Table_head.csv': [], 'Table_AmfPointer.csv': [], 'Table_AmfRegionID.csv': [] }, # ...其他logtype }
方式2:使用深拷贝生成子字典
如果需要复用模板,要用copy.deepcopy()完全复制模板中的所有对象(包括内部的列表):
import copy table_template = { 'Table_AmfSetID.csv': [], 'Table_QCI.csv': [], 'Table_body.csv': [], 'Table_head.csv': [], 'Table_AmfPointer.csv': [], 'Table_AmfRegionID.csv': [] } logtype_files_library = { 'logtype16777217': copy.deepcopy(table_template), 'logtype16777218': copy.deepcopy(table_template), # ...其他logtype }
方式3:动态生成子字典
如果logtype数量较多,可用循环动态创建每个子字典,确保每个列表都是新的:
logtypes = ['logtype16777217', 'logtype16777218', ...] table_names = [ 'Table_AmfSetID.csv', 'Table_QCI.csv', 'Table_body.csv', 'Table_head.csv', 'Table_AmfPointer.csv', 'Table_AmfRegionID.csv' ] logtype_files_library = { logtype: {table: [] for table in table_names} for logtype in logtypes }
修改后再运行原循环代码,每个文件路径就会被正确追加到对应的logtype下的table列表中。
内容的提问来源于stack exchange,提问作者TRP
相关产品推荐
相关产品推荐

