1

Forgive my Python noob-ism, but I have written this pattern in several other languages, and can't find a boilerplate for Python that seems... pythonic, I guess.

I want a base class that either takes a set of default parameters, or loads itself from a file. It then has a save() method that saves its instance data to the given named file.

Critically, I want to be able to modify the classes that inherit from the base class to add or remove attributes, and still have the old attributes loaded from the old files. This code appears to work (2.7):

import pickle
class Thing(object):
    def __init__(self, filename=''):
        self.filename = filename
        if self.filename:
            self._load()
    def save(self):
        with open(self.filename, 'wb') as f:
            pickle.dump(self,f)
    def _load(self):
        try:
            with open(self.filename, 'rb') as f:
                self.__dict__.update(pickle.load(f).__dict__)
            return True
        except:
            return False

Then the inheriting class:

class BiggerThing(Thing):
    def __init__(self, filename='', x=0, y=0):
        self.x = x
        self.y = y
        #self.whoops = 'swell'
        super(BiggerThing, self).__init__(filename)

This seems to work: I can do:

t = BiggerThing('file.pickle', x=1, y=2)
t.save()

And I'll get the the proper object when I do:

t2 = BiggerThing('file.pickle')

And equally important, if I un-comment the 'self.whoops' line and load the old file, I still get back the object with x=1 and y=2, and can then save() the new object with 'whoops' set.

This just seems like it would be a common pattern for making self-loadable objects, but I haven't seen it like this and wonder if it's because it isn't very pythonic?

Eric
  • 11
  • 2
  • 2
    I don't think it's particularly unpythonic (or not). For a large application I'd probably want the save/load logic in another object though, otherwise your classes will end up have too many responsibilities. – snakecharmerb Apr 02 '16 at 07:19
  • Is the object so large (or your allowed memory so small) that you need to involve the filesystem, or are you trying to protect the parent object data from the subclass? If you're aim is data protection, you can avoid the file system my using [name mangling](http://programmers.stackexchange.com/questions/229804/usage-of-while-declaring-any-variables-or-class-member-in-python) – willnx Apr 02 '16 at 07:27
  • 1
    Have you read https://docs.python.org/3/library/pickle.html#pickle-state and https://docs.python.org/3/library/pickle.html#pickling-class-instances? Seems like something you'd be interested in. – Ilja Everilä Apr 02 '16 at 08:02
  • @snakecharmerb - this is the closest to an answer or opinion. I was trying to rationalize the convenience of a self-loading/saving object, which I typically use (in other languages) for small configuration-type objects that are generally bound to the same file. But you're right in that more complex objects may want their load/save unbound for flexibility. – Eric Apr 02 '16 at 14:51
  • @willnx -- neither, really. I just want a persistent object so that when the code starts up again, the object gets its last state. – Eric Apr 02 '16 at 14:52
  • @llja -- thanks for that reference. I was using http://stackoverflow.com/questions/2709800/how-to-pickle-yourself which illustrates the problem of unpickling a class instance when the attributes of the class have changed. From what I gather from your reference, __getnewargs__() can be used to help this, but unfortunately there's no example. – Eric Apr 02 '16 at 14:55

0 Answers0