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

SimPy日志写入Pandas DataFrame后类外读取为空的问题排查

问题根因
  • 核心是类属性与实例属性的作用域混淆:你在类定义层级初始化的s_df是类级别的共享属性,但在do_somehting方法中执行self.s_df = self.s_df.append(...)时,赋值操作会给当前运行的Seller实例单独创建一个同名实例属性,后续所有append生成的新DataFrame都绑定在各个实例自己身上。你在方法内部打印看到的数据增长,实际是各个实例自有s_df的变化,类本身持有的s_df始终是初始化时的空DataFrame,所以外部调用类方法df()拿到的永远是空值。
  • 语法问题:原代码__init__方法中self._s_list.append(self)这一行缩进多了一级,直接运行会报缩进错误。
  • 性能问题:pandas的append方法每次调用都会生成全新的DataFrame对象,仿真循环里高频调用的性能极差,不适合做运行时日志存储。
修复后代码
import pandas as pd
import simpy

class Seller(object):
    _s_list = []     # 存储所有卖家实例
    _log_records = [] # 运行时先用列表存日志,避免频繁拼接DataFrame

    def __init__ (self, env, name):
        self._s_list.append(self)
        self.env, self.name = env, name
        self.action = env.process(self.do_something())

    def do_something(self):
        while True:
            # 直接往类级别的日志列表追加记录,不给实例绑定同名属性
            self._log_records.append({
                "time": self.env.now,
                "name": self.name,
            })
            yield self.env.timeout(1)

    @classmethod
    def lst(cls):
        return cls._s_list

    @classmethod
    def df(cls):
        # 需要取数时一次性把列表转为DataFrame
        return pd.DataFrame.from_dict(cls._log_records)

env = simpy.Environment()
for i in range(0,3):
    Seller(env, "seller n. %d" % i)
env.run(until=5)
print(Seller.lst())
print(Seller.df())
修复说明
  • 把运行时日志存储介质从DataFrame换成普通列表,列表的append是原地操作,性能比反复拼接DataFrame高几个数量级,适配仿真场景的高频写入需求。
  • 所有类级别的共享数据操作,避免通过self.xxx = 的形式赋值,防止意外创建实例属性覆盖类属性引用。类方法中统一用cls指代类本身,实例方法中如果要修改类属性,直接通过类名或者self.__class__引用即可。
  • 同步修正了原代码的缩进错误、方法名拼写错误(原do_somehting改为正确拼写do_something)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.27 04:57:24