为什么类方法找不到在对象初始化中定义的属性?

2024-10-03 23:27:15 发布

您现在位置:Python中文网/ 问答频道 /正文

我已经构建了一个PickleJar类,我打算像字典一样工作(它将有一个内置方法的字典子集,允许像字典一样访问它)。问题在于,当从PickleJar中添加或删除对象时,它会更新我笔记本电脑上的本地副本

class PickleJar():
    '''
    Class used for storing objects locally. It is accessed like a dictionary, and anytime a new item is added,
    the pickled version of the dictionary is also updated on local disk.
    Example:
        jar = PickleJar()
        jar['ObjectId(18452298134587901458)'] = Object
    Args:
        name (str)  :   Name of the local pickle file which this class is bound to
        loc (str)   :   Location of the pickle file specified by name
    '''
    def __init__(self, name:str, loc=r'C:\Users\path\to\.pickle'):
        loc = Path(loc)
        jar_path = os.path.join(loc, Path(name))
        if os.path.exists(jar_path):
            with open(jar_path, 'rb') as fopen:
                temp = pickle.load(fopen)
            assert isinstance(temp, dict), "Expected a dict with key: value pairs of Key: Object"
            self.jar_path = jar_path
            self.__dict__ = temp
        else:
            self.jar_path = jar_path
            self.__dict__ = dict()

    def __setitem__(self, key:str, item:ConcurrentExecutionGraph):
        '''Any time this object has a key set to a value, it will update it in the local pickle dictionary'''
        with open(self.jar_path, 'rb') as fopen:
            disk_pickle = pickle.load(fopen)
            disk_pickle[key]=item
        with open(self.jar_path, 'wb') as fopen:
            pickle.dump(disk_pickle, fopen)
        self.__dict__[key] = item

    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):
        with open(self.jar_path, 'rb') as fopen:
            disk_pickle = pickle.load(fopen)
            del disk_pickle[key]
        with open(self.jar_path, 'wb') as fopen:
            pickle.dump(disk_pickle, fopen)
        del self.__dict__[key]

    def keys(self):
        return self.__dict__.keys()

    def values(self):
        return self.__dict__.values()

    def items(self):
        return self.__dict__.items()

问题是,在PickleJar初始化之后,我尝试调用它的__setitem__方法,它抱怨self.jar_path不再存在,尽管我在__init__中显式地设置了它。我已经通过单步执行代码验证了self.jar_path在初始化过程中确实得到了设置

Key = "SomeKey"
Object = "SomeObject"
basejar = PickleJar("BaselinePickleJar.pkl")
basejar[Key] = SomeObject

我得到一个错误:

Exception has occurred: AttributeError
'PickleJar' object has no attribute 'jar_path'
  File "C:\Users\...\memory.py", line 426, in __setitem__
    with open(self.jar_path, 'rb') as fopen:
  File "C:\Users\...\memory.py", line 330, in __init__
    basejar[Key] = SomeObject
  File "C:\Users\...\train.py", line 39, in main
    data_manager = DataManager(args)
  File "C:\Users\...\train.py", line 134, in <module>
    main(args, kwargs)

Tags: thepathkeyselfreturndefaswith
1条回答
网友
1楼 · 发布于 2024-10-03 23:27:15

设置self.__dict__将所有属性替换为字典中的项。所以你失去了self.jar_path的值

简单的解决方案是在设置self.__dict__之后设置self.jar_path

    def __init__(self, name:str, loc=r'C:\Users\path\to\.pickle'):
        loc = Path(loc)
        jar_path = os.path.join(loc, Path(name))
        if os.path.exists(jar_path):
            with open(jar_path, 'rb') as fopen:
                temp = pickle.load(fopen)
            assert isinstance(temp, dict), "Expected a dict with key: value pairs of Key: Object"
            self.__dict__ = temp
        else:
            self.__dict__ = dict()
        self.jar_path = jar_path

相关问题 更多 >