Faur
Faur

Reputation: 5968

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 :/

Upvotes: 0

Views: 1175

Answers (1)

Mathias Rav
Mathias Rav

Reputation: 2973

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__?

Upvotes: 2

Related Questions