Python3.x:如何在类中保存和加载数据

Python3.x:如何在类中保存和加载数据,python,python-3.x,Python,Python 3.x,我想要一个类,它在初始化时检查filename是否存在。如果它这样做了,它应该用文件名初始化自己,否则它应该运行init。稍后,我可以运行save方法,保存整个对象 我想要的东西的草图: class data(object): def __init__(self, filename): if does_not_exist(filename): # create new [... expensive computations]

我想要一个类,它在初始化时检查
filename
是否存在。如果它这样做了,它应该用
文件名
初始化自己,否则它应该运行init。稍后,我可以运行
save
方法,保存整个对象

我想要的东西的草图:

class data(object):
    def __init__(self, filename):
        if does_not_exist(filename): # create new
             [... expensive computations]
             self.save(filename)
        else: # load existing
            with open(filename,'rb') as fp:
                self = pickle.load(fp)

    def save(self, filename):
        with open(filename,'wb') as fp:
        pickle.dump(self, fp)
加载时,我知道我可以执行以下操作

tmp = pickle.load(fp)
    self.a = tmp.a
    self.b = tmb.b
    ...
但我希望有更好的办法



我假设以前有人问过这个问题,但找不到:/

\uuuu init\uuuu
中分配给
self
是没有意义的,因为您没有修改
self
指向的对象——您只是将函数中的变量名
self
绑定到另一个对象

您可以使用
staticmethod
classmethod
从缓存执行可选加载:

class Data(object):
    @classmethod
    def init_cached(cls, filename):
        if not os.path.exists(filename):  # create new
            result = cls(filename)
            result.save(filename)
            return result
        else:
            with open(filename, 'rb') as fp:
                return pickle.load(fp)

    def __init__(self, filename):
        pass  # [... expensive computations]
现在,使用
Data.init\u cached()
而不是
Data()
来初始化对象


一种更奇特的方法是覆盖
数据。\uuuu new\uuu()
以实现同样的效果,但使用
数据()进行初始化时,会透明地检查缓存版本是否存在:

class Data(object):
    def __new__(cls, filename):
        if not os.path.exists(filename):  # create new
            return super(Data, cls).__new__(cls, filename, _save=True)
        else:
            with open(filename, 'rb') as fp:
                return pickle.load(fp)

    def __init__(self, filename, _save=False):
        # [... expensive computations]
        if _save:
            self.save(filename)

进一步阅读:

\uuu init\uuu
中分配给
self
是没有意义的,因为您没有修改
self
指向的对象——您只是将函数中的变量名
self
绑定到另一个对象

您可以使用
staticmethod
classmethod
从缓存执行可选加载:

class Data(object):
    @classmethod
    def init_cached(cls, filename):
        if not os.path.exists(filename):  # create new
            result = cls(filename)
            result.save(filename)
            return result
        else:
            with open(filename, 'rb') as fp:
                return pickle.load(fp)

    def __init__(self, filename):
        pass  # [... expensive computations]
现在,使用
Data.init\u cached()
而不是
Data()
来初始化对象


一种更奇特的方法是覆盖
数据。\uuuu new\uuu()
以实现同样的效果,但使用
数据()进行初始化时,会透明地检查缓存版本是否存在:

class Data(object):
    def __new__(cls, filename):
        if not os.path.exists(filename):  # create new
            return super(Data, cls).__new__(cls, filename, _save=True)
        else:
            with open(filename, 'rb') as fp:
                return pickle.load(fp)

    def __init__(self, filename, _save=False):
        # [... expensive computations]
        if _save:
            self.save(filename)

进一步阅读:

为什么要对整个对象进行酸洗?只Pickle您需要的存储数据-您已经加载了结构,因此尝试将其与数据一起保存没有任何意义。同意。我只是不知道如何以简洁的方式存储所有数据。我更愿意不必为数据对象写东西。我该怎么做呢?您可以使用
\uuuuu setstate\uuuu
只对相关数据进行pickle,然后使用
\uuuu getstate\uuuuu
魔术方法将其加载回。它不仅使您能够更好地控制如何保存和恢复与实例相关的数据,而且还使pickle不太容易出错(意外的类覆盖等)。参见第三个示例:为什么要对整个对象进行酸洗?只Pickle您需要的存储数据-您已经加载了结构,因此尝试将其与数据一起保存没有任何意义。同意。我只是不知道如何以简洁的方式存储所有数据。我更愿意不必为数据对象写东西。我该怎么做呢?您可以使用
\uuuuu setstate\uuuu
只对相关数据进行pickle,然后使用
\uuuu getstate\uuuuu
魔术方法将其加载回。它不仅使您能够更好地控制如何保存和恢复与实例相关的数据,而且还使pickle不太容易出错(意外的类覆盖等)。参见第三个示例: