Toke Faurby Toke Faurby - 1 year ago 102
Python Question

Python 3.x: How to save and load data from within a class

I would like a class that in its initialize checks if

filename
exists. If it does it should initialize itself with
filename
, otherwise it should run init. At a later point I can then run a
save
method, saving the entire object.

A sketch of what I want:

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)


When loading I know that I can do something like

tmp = pickle.load(fp)
self.a = tmp.a
self.b = tmb.b
...


But I hope that there is a better way




I assume this question has been asked before, but couldn't find it :/

Answer Source

Assigning to self within __init__ is meaningless, since you're not modifying the object that self points to -- you're just binding the variable name self in the function to a different object.

What you can do instead is use a staticmethod or classmethod to perform the optional loading from cache:

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]

Now, use Data.init_cached() instead of Data() to initialize your object.


A more fancy approach would involve overriding Data.__new__() to achieve the same thing, but where initialization with Data() transparently checks if a cached version exists:

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)

Further reading: Python's use of __new__ and __init__?

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download