Python循环中向list添加dict时元素被覆盖的原因咨询
问题原因与解决方法
原因分析
你遇到的问题核心在于Python中字典是可变对象:你在循环外仅创建了一个dt字典,每次循环只是更新该字典的键值对,随后将这个字典的内存引用添加到列表ls中。列表里的所有元素本质上都指向同一个内存地址的字典对象,因此当最后一次更新字典后,列表里的所有元素都会同步显示这个最终的字典内容——所谓的“前序元素被覆盖”,其实是它们从始至终都指向同一个对象。
解决方法
有两种简单的修复方式:
方法1:每次循环内新建字典
将字典的创建逻辑放到循环内部,这样每次迭代都会生成一个全新的字典对象,添加到列表中的都是独立的引用:
def logs(): with open("assets/logdata.txt", "r") as file: logdata = file.read() # 修正正则表达式的转义符,原始字符串中单个\即可 tp = re.findall(r'([0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3})\s-\s([a-zA-Z0-9]+|[-])\s\[(.*)\]\s"(.*)"',logdata) ls = list() for itp in tp: # 每次循环新建独立字典 dt = dict() dt['host'] = itp[0] dt['user_name'] = itp[1] dt['time'] = itp[2] dt['request'] = itp[3] ls.append(dt) return ls
方法2:添加字典的副本到列表
如果需要保留循环外的字典初始化逻辑,可以在append时添加字典的浅拷贝副本,确保列表元素是独立的对象:
def logs(): with open("assets/logdata.txt", "r") as file: logdata = file.read() tp = re.findall(r'([0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3})\s-\s([a-zA-Z0-9]+|[-])\s\[(.*)\]\s"(.*)"',logdata) ls = list() dt = dict() for itp in tp: dt['host'] = itp[0] dt['user_name'] = itp[1] dt['time'] = itp[2] dt['request'] = itp[3] # 添加字典的浅拷贝,生成独立对象 ls.append(dt.copy()) return ls
内容的提问来源于stack exchange,提问作者LunaPapa
相关产品推荐
相关产品推荐

