Python读取JSON文件customer_info异常:仅获取最后一个客户数据求助
问题:读取JSON客户数据时所有条目均返回最后一个客户的信息
问题描述
从JSON文件读取customer_info数据后,返回的客户列表中所有条目都指向最后一个客户的数据。例如执行print(listcustomer[0].food[0].name)时,得到的是第二个客户的第二个食物名称,而非第一个客户的第一个食物名称。
JSON数据
{ "customer_info": [ { "Table ID" : "0001", "Food":[ {"Name": "Pizza", "Amount": "2", "Price":"4"}, {"Name": "Chicken", "Amount": "3", "Price":"7.5"} ], "Total bill" : "200", "Time order" : "6:00pm", "Time by sec" : "0183287783", "Status" : "Paid" }, { "Table ID" : "0003", "Food":[ {"Name": "Hamburger", "Amount": "2", "Price":"4.4"}, {"Name": "Soup", "Amount": "3", "Price":"7.5"} ], "Total bill" : "200", "Time order" : "6:00pm", "Time by sec" : "0183287783", "Status" : "Paid" } ], "food_initial_info":[ { "Name" : "Pizza", "Price" : "2" }, { "Name": "Fried Chicken", "Price": "1.8" }, { "Name": "Soup", "Price": "2.5" }, { "Name": "Beef", "Price": "4.2" }, { "Name": "Spaghetti", "Price": "3.5" }, { "Name": "Hamburger", "Price": "2.2" } ] }
原Python代码
import json import time class Food: name = "" price = "" amount = "" food_own_bill = "" def __init__(self, name, price): self.name = name self.price = price def food_bill(self): self.food_own_bill =str(int(self.price) * int(self.amount)) class Customer: table_id = "" food = [] total_bill = "" time_order = "" time_by_sec = "" status = "" def __init__(self, table_id, food, time_order, time_by_sec, status): self.table_id = table_id self.time_order = time_order self.time_by_sec = time_by_sec self.status = status for item in food: self.food.append(item) def calculate_bill(self): bill = 0 for item in self.food: bill += item.food_bill() def load_customer_info(fileName): with open (fileName) as filejson: data = json.load(filejson) listcustomer = [] for item in data["customer_info"]: new_customer = Customer new_customer.table_id = item["Table ID"] new_customer.total_bill = item["Total bill"] new_customer.time_order = item["Time order"] new_customer.time_by_sec = item["Time by sec"] new_customer.status = item["Status"] for food_info in item["Food"]: new_food = Food new_food.name = food_info["Name"] new_food.amount = food_info["Amount"] new_food.food_own_bill = food_info["Price"] new_customer.food.append(new_food) listcustomer.append(new_customer) return listcustomer listcustomer = load_customer_info("data.json") print(listcustomer[0].food[0].name)
问题根源
- 直接操作类而非实例化对象:
new_customer = Customer和new_food = Food是将类本身赋值给变量,而非创建类的实例。每次循环都会修改类的全局属性,所有"实例"最终都会指向最后一次修改的类属性。 - 类变量与实例变量混淆:
Customer类中的food = []是类变量,所有实例共享同一个列表。循环添加食物时,会持续往这个共享列表中追加数据,导致所有客户的食物列表混杂在一起。 - 类型转换错误:原代码中
int(self.price)会因price为浮点数字符串(如"7.5")引发报错。
修正后的代码
import json class Food: def __init__(self, name, price, amount): # 所有属性定义为实例变量,初始化时传入完整参数 self.name = name self.price = price self.amount = amount # 直接计算单类食物账单,避免后续调用方法的麻烦,同时修复类型转换问题 self.food_own_bill = str(float(price) * int(amount)) class Customer: def __init__(self, table_id, foods, total_bill, time_order, time_by_sec, status): # 所有属性定义为实例变量,确保每个客户有独立的属性空间 self.table_id = table_id self.food = foods self.total_bill = total_bill self.time_order = time_order self.time_by_sec = time_by_sec self.status = status def calculate_bill(self): bill = 0.0 for item in self.food: bill += float(item.food_own_bill) return bill def load_customer_info(fileName): with open(fileName) as filejson: data = json.load(filejson) listcustomer = [] for item in data["customer_info"]: # 先构建当前客户的食物实例列表 foods_list = [] for food_info in item["Food"]: # 正确实例化Food对象,传入所需参数 new_food = Food( name=food_info["Name"], price=food_info["Price"], amount=food_info["Amount"] ) foods_list.append(new_food) # 正确实例化Customer对象,传入所有必要参数 new_customer = Customer( table_id=item["Table ID"], foods=foods_list, total_bill=item["Total bill"], time_order=item["Time order"], time_by_sec=item["Time by sec"], status=item["Status"] ) listcustomer.append(new_customer) return listcustomer listcustomer = load_customer_info("data.json") print(listcustomer[0].food[0].name) # 输出:Pizza print(listcustomer[1].food[0].name) # 输出:Hamburger
关键修正说明
- 实例化对象:使用
Customer(...)和Food(...)创建类的实例,每个实例拥有独立的属性空间,不会互相覆盖。 - 区分类变量与实例变量:移除类级别的属性定义,所有属性在
__init__方法中初始化,确保每个实例的属性独立。 - 修复类型错误:将
int(self.price)改为float(price),支持浮点数价格的计算。 - 优化逻辑:先构建完整的食物列表再传入客户实例,代码逻辑更清晰,避免共享列表的问题。
内容的提问来源于stack exchange,提问作者Phúc Hoàng
相关产品推荐
相关产品推荐

