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

使用pickle存储SymPy对象报错:'One'对象不可订阅

SymPy线性方程组缓存报错:'One' object is not subscriptable 解决方法

问题场景

用SymPy求解线性方程组时计算耗时较长,为重复使用结果,通过pickle将计算结果缓存到磁盘,但修改后的代码运行时报错:

TypeError: 'One' object is not subscriptable

报错代码

@property
def solutions(self) -> list[Expr]:
    directory = SYMPY_DATA_PATH
    filename = os.path.join(directory, f'{self.__class__.__name__}.pkl')
    if not os.path.exists(directory):
        os.makedirs(directory)
    if os.path.exists(filename):
        with open(filename, 'rb') as f:
            print(f"Loading {filename}")
            solution_set = pickle.load(f)
    else:
        solution_set = together(linsolve(self.equations, self.pins))
        print(f"Saving {filename}")
        with open(filename, 'wb') as f:
            pickle.dump(list(solution_set)[0], f)
    return list(solution_set)[0]

def solution(self, pin) -> Expr:
    return self.solutions[pin]

原正常运行代码

@property
def solutions(self) -> list[Expr]:
    solution_set = together(linsolve(self.equations, self.pins))
    return list(solution_set)[0]

错误原因

缓存逻辑存在不一致:

  • 首次计算时,solution_set是SymPy的解集对象(如FiniteSet),我们将list(solution_set)[0](即最终需要的解列表)存入pickle。
  • 加载缓存时,直接将解列表赋值给了solution_set,随后又执行list(solution_set)[0]——这相当于把解列表的第一个元素(单个SymPy表达式)作为返回值。
  • 调用solution方法时,self.solutions实际是单个表达式对象(而非列表),对其做下标操作自然触发"不可下标"的错误。

修复代码

调整缓存逻辑,直接缓存并返回解列表,避免重复转换:

@property
def solutions(self) -> list[Expr]:
    directory = SYMPY_DATA_PATH
    filename = os.path.join(directory, f'{self.__class__.__name__}.pkl')
    if not os.path.exists(directory):
        os.makedirs(directory)
    if os.path.exists(filename):
        with open(filename, 'rb') as f:
            print(f"Loading {filename}")
            # 直接加载缓存的解列表
            solution_list = pickle.load(f)
    else:
        solution_set = together(linsolve(self.equations, self.pins))
        solution_list = list(solution_set)[0]
        print(f"Saving {filename}")
        with open(filename, 'wb') as f:
            pickle.dump(solution_list, f)
    # 直接返回解列表
    return solution_list

def solution(self, pin) -> Expr:
    return self.solutions[pin]

修复说明

  • 首次计算时,直接提取解列表并缓存,后续加载时直接复用该列表。
  • 无论计算还是加载,solutions属性始终返回解列表,调用solution方法时的下标操作会正常作用于列表,避免报错。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.01 21:40:22