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

为何for循环会异常覆盖Python字典内容?

问题:Pandas转JSON时所有月份数据被最后一个月覆盖

尝试将Pandas DataFrame转换为JSON格式,先转Python字典再转JSON,但出现异常:所有月份的数据都被最后一次循环的月份数据覆盖。调试时数据处理顺序正确,但最终JSON输出不符合预期。

可复现代码

主文件代码:

import re
import pandas as pd
import json

from help import Model  # 引入另一个文件help.py

jan = {'Month': ["January", "January", "January", "January"],
       'Date': ['1st', '2nd', '28th', '29th'],
       'a': ["j1a", "a3x", "d9c", "h9c"],
       'b': ["X1", "SG", "DV", "XP"]}

dec = {'Month': ["December", "December", "December", "December"],
       'Date': ['1st', '2nd', '28th', '29th'],
       'a': ["d1a", "o3x", "j9c", "h9c"],
       'b': ["X2", "SG", "DV", "XP"]}

a = pd.DataFrame.from_dict(jan)
b = pd.DataFrame.from_dict(dec)

dfs = [a, b]
df = pd.concat(dfs)

DateNum = []
for values in df['Date']:
    DateNum.append(re.search(r'\d+', values).group())
df['Date Num'] = DateNum
df.reset_index(drop=True, inplace=True)

dfl = df.Month.tolist()
months = []
for data in dfl:
    if data not in months:
        months.append(data)
# months = ['January', 'December']
models = []
for month in months:
    models.append(Model(month))


calendar = {}
for month in models:
    datacopy = df.copy()
    datacopy = datacopy[datacopy.Month == month.name]
    month.data = datacopy

    month.update(debug=True)
    calendar[month.name] = month.days

print(json.dumps(calendar, indent=4))

help.py文件代码:

class Model:
    """
    model for months
    """
    name = ""
    data = None

    days = {}

    def __init__(self, monthname):
        self.name = monthname

    def update(self, debug=False):

        edit = self.data  # a copy of a slice from the df
        edit = edit.drop("Month", axis=1)  # drop Month column
        edit = edit.set_index('Date Num').T.to_dict('list')  # set Date Num column to be the index and make dict

        data_formatted = {self.name: edit}  # save the dict with key as month name as data_formatted

        for k, v in data_formatted[self.name].items():  # data_formatted [month] = (day number : data)

            if debug:
                print(k, v)  # e.g. k=1 v=['1st', 'a', 'n']

            day_object = Day(v)  # make a day object out of the values (formatting in initializer)
            self.days[k] = day_object.data_formatted  # assign the formatted value e.g. days[1] = (formatted data)

            # print(self.days[k])  # shows correct data e.g. {'date': '25th', 'a': 'a', 'b': 'n', 'c': 'x'}


class Day:
    date = ""
    a = ""
    b = ""

    data_formatted = {}

    def __init__(self, data):
        self.date = data[0]
        self.a = data[1]
        self.b = data[2]

        self.format_data()

    def format_data(self):
        self.data_formatted = {
            "date": self.date,
            "a": self.a,
            "b": self.b,
        }

调试输出(正常)

1 ['1st', 'j1a', 'X1']
2 ['2nd', 'a3x', 'SG']
28 ['28th', 'd9c', 'DV']
29 ['29th', 'h9c', 'XP']
1 ['1st', 'd1a', 'X2']
2 ['2nd', 'o3x', 'SG']
28 ['28th', 'j9c', 'DV']
29 ['29th', 'h9c', 'XP']

异常JSON输出

{
"January": {
    "1": {
        "date": "1st",
        "a": "d1a", // 应为j1a
        "b": "X2" // 应为X1
    },
    "2": {
        "date": "2nd",
        "a": "o3x", // 应为a3x
        "b": "SG"
    } ...
}

原因分析

问题出在类变量与实例变量的混淆:

  • Model类中的days = {}是类变量,所有Model实例会共享同一个字典对象。当第二个Model实例(December)更新days时,会直接覆盖第一个实例(January)的days内容,因为它们指向同一个内存地址。
  • Day类中的data_formatted = {}同样是类变量,但在__init__中用self.data_formatted重新赋值为实例变量,所以这部分没有引发问题,但为了规范建议统一改为实例变量。

解决方案

将Model类中的days从类变量改为实例变量,在__init__方法中初始化;同时清理Day类中的冗余类变量:

修改后的help.py代码:

class Model:
    """
    model for months
    """
    def __init__(self, monthname):
        self.name = monthname
        self.data = None
        self.days = {}  # 改为实例变量,每个实例独立拥有

    def update(self, debug=False):
        edit = self.data.drop("Month", axis=1)
        edit = edit.set_index('Date Num').T.to_dict('list')

        for k, v in edit.items():
            if debug:
                print(k, v)
            day_object = Day(v)
            self.days[k] = day_object.data_formatted


class Day:
    def __init__(self, data):
        self.date = data[0]
        self.a = data[1]
        self.b = data[2]
        self.data_formatted = {}  # 初始化实例变量
        self.format_data()

    def format_data(self):
        self.data_formatted = {
            "date": self.date,
            "a": self.a,
            "b": self.b,
        }

修复后输出

运行主文件后,JSON输出将符合预期:

{
    "January": {
        "1": {
            "date": "1st",
            "a": "j1a",
            "b": "X1"
        },
        "2": {
            "date": "2nd",
            "a": "a3x",
            "b": "SG"
        },
        "28": {
            "date": "28th",
            "a": "d9c",
            "b": "DV"
        },
        "29": {
            "date": "29th",
            "a": "h9c",
            "b": "XP"
        }
    },
    "December": {
        "1": {
            "date": "1st",
            "a": "d1a",
            "b": "X2"
        },
        "2": {
            "date": "2nd",
            "a": "o3x",
            "b": "SG"
        },
        "28": {
            "date": "28th",
            "a": "j9c",
            "b": "DV"
        },
        "29": {
            "date": "29th",
            "a": "h9c",
            "b": "XP"
        }
    }
}

内容的提问来源于stack exchange,提问作者mfm

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.24 14:45:56