如何让Python列表正确存储每次用户输入生成的独立字典
问题描述
编写个人预算统计Python脚本时预期实现逻辑:
- 第一步接收用户输入的净收入
- 循环询问用户是否添加支出项
- 每次循环收集三类信息:支出名称描述、预算金额、支出类型(需要/想要/储蓄),存入字典后追加到
budget列表中
实际运行出现异常:每次循环更新字典内容后,列表中之前存储的所有字典条目都会被新输入的内容覆盖,最终输出的列表内所有元素均为最后一次输入的字典内容。最初误将字典追加操作写为budget.update(),修正为budget.append()后问题仍然存在。
问题复现代码
#line used to accept user's net pay net_income = float(input("Please enter your net income: ")) #line used to query if user wants to input budgeted line item add_exp_item= input("Do you want to add an expenditure item (yes or no): ").lower() #intialization of dictionary and list used to store user input budget = [] budget_listItem = {} #loop used to continuously query for budgeted expense item while True: #line used to store description of expense d= input("Enter name description of expense: ") #line used to store numerical value of expense a = float(input("Enter cost/budgeted amount: ")) #line used to store the type of expense t = input("Enter category type that such as whether it is a want, need, saving: ") #line used to store all user input in dictionary budget_listItem.update({'description': d, 'amount': a, 'type': t}) #testing line to to see what is stored in dictionary print(budget_listItem) #line used to store each expense line (each dictionary) in a list budget.append(budget_listItem) #testing line to check what is in list of dictionaries print(budget) #line used to query if user wants to enter another line item add_exp_item= input("Do you want to add an expenditure item (yes or no): ").lower() print("*************************************************** \n") #bool used to break out of loop if user no longer wants to enter line items if add_exp_item == "no": break print("\n \n") #final print of list of dictionaries print(budget)
问题根因
Python中字典属于可变引用类型,代码在循环外仅初始化了1次budget_listItem字典,整个循环运行过程中操作的始终是同一个内存地址的字典对象。
执行budget.append(budget_listItem)时,追加到列表中的不是字典内容的独立副本,而是该字典的内存引用——也就是说列表里存储的所有条目本质上都指向同一个字典对象,后续调用budget_listItem.update()修改字典内容时,所有指向该对象的列表条目会同步更新为最新值,最终表现为所有列表元素都和最后一次输入的内容一致。
修复方案
二选一即可解决问题:
- 将
budget_listItem = {}的字典初始化逻辑移到while True循环内部,每次处理新支出项时都创建一个全新的独立字典,保证每次追加到列表的都是互不干扰的新对象。 - 保留循环外的字典初始化逻辑,追加时传入字典的浅拷贝,将追加语句修改为
budget.append(budget_listItem.copy()),这样每次存入列表的是当前字典内容的独立快照,后续修改原字典不会影响已经存入列表的内容。
修正后核心代码参考(采用第一种方案)
net_income = float(input("Please enter your net income: ")) add_exp_item= input("Do you want to add an expenditure item (yes or no): ").lower() budget = [] while True: # 每次循环新建独立字典存储当前支出 budget_listItem = {} d= input("Enter name description of expense: ") a = float(input("Enter cost/budgeted amount: ")) t = input("Enter category type that such as whether it is a want, need, saving: ") budget_listItem.update({'description': d, 'amount': a, 'type': t}) budget.append(budget_listItem) add_exp_item= input("Do you want to add an expenditure item (yes or no): ").lower() print("*************************************************** \n") if add_exp_item == "no": break print(budget)
内容的提问来源于stack exchange,提问作者Drey'
相关产品推荐
相关产品推荐

