Python自定义PickleJar类调用__setitem__提示无jar_path属性如何解决?
问题根因
Python 类实例的所有属性默认存储在self.__dict__内置字典中,你代码的错误出在__init__方法的赋值顺序:
- 你先计算得到
jar_path路径,给self.jar_path赋值,此时该属性被写入self.__dict__ - 紧接着你直接执行
self.__dict__ = temp(读取已有pickle文件的分支)或者self.__dict__ = dict()(新建文件的分支),将实例的属性字典整体替换,上一步写入的jar_path被直接覆盖丢失,后续调用__setitem__时自然找不到该属性。
修复方案
调整__init__方法的赋值顺序,先替换self.__dict__,再给self.jar_path赋值,确保该属性不会被覆盖。同时补充缺失的初始化逻辑,避免新文件首次调用方法时报错:
import pickle import os from pathlib import Path class PickleJar(): ''' 用于本地存储对象的类,支持类字典的访问方式,每次新增/删除元素时都会自动更新本地pickle文件 示例: jar = PickleJar() jar['ObjectId(18452298134587901458)'] = Object 参数: name (str) : 绑定的本地pickle文件名称 loc (str) : pickle文件存储路径 ''' def __init__(self, name:str, loc=r'C:\Users\path\to\.pickle'): loc = Path(loc) # 自动创建存储目录,避免路径不存在报错 loc.mkdir(exist_ok=True, parents=True) jar_path = loc / Path(name) if jar_path.exists(): with open(jar_path, 'rb') as fopen: temp = pickle.load(fopen) assert isinstance(temp, dict), "预期存储格式为键值对字典" # 先替换属性字典 self.__dict__ = temp # 再赋值jar_path,确保不会被覆盖 self.jar_path = jar_path else: # 先初始化空白属性字典 self.__dict__ = dict() # 再赋值jar_path self.jar_path = jar_path # 新文件初始化时写入空白字典到磁盘,避免首次写操作读文件报错 with open(jar_path, 'wb') as fopen: pickle.dump(self.__dict__, fopen) def __setitem__(self, key:str, item): '''设置元素时自动同步到本地pickle文件''' self.__dict__[key] = item # 直接写入内存最新数据即可,无需额外读磁盘,减少IO开销 with open(self.jar_path, 'wb') as fopen: pickle.dump(self.__dict__, fopen) def __getitem__(self, key): return self.__dict__[key] def __repr__(self): return repr(self.__dict__) def __len__(self): return len(self.__dict__) def __delitem__(self, key): del self.__dict__[key] with open(self.jar_path, 'wb') as fopen: pickle.dump(self.__dict__, fopen) def keys(self): return self.__dict__.keys() def values(self): return self.__dict__.values() def items(self): return self.__dict__.items()
可选优化说明
原__setitem__和__delitem__实现中每次都先读取磁盘文件再写入,不仅IO开销大,还可能出现内存和磁盘数据不一致的问题。优化后直接写入内存中最新的self.__dict__,逻辑更简洁效率更高。
内容的提问来源于stack exchange,提问作者Jake Daly
相关产品推荐
相关产品推荐

