You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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)

问题根源

  1. 直接操作类而非实例化对象:new_customer = Customer和new_food = Food是将类本身赋值给变量,而非创建类的实例。每次循环都会修改类的全局属性,所有"实例"最终都会指向最后一次修改的类属性。
  2. 类变量与实例变量混淆:Customer类中的food = []是类变量,所有实例共享同一个列表。循环添加食物时,会持续往这个共享列表中追加数据,导致所有客户的食物列表混杂在一起。
  3. 类型转换错误:原代码中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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.25 22:54:35