David Poxon
David Poxon

Reputation: 2503

__new__ not calling __init__ when correct class

I have a class Vertex()

With the following methods:

def __new__(cls, pos_x, pos_y, size_x, size_y, text):
        instance = super(Vertex, cls).__new__(cls)
        #print 'variables {0}, {1}, {2}, {3}, {4}'.format(pos_x, pos_y, size_x, size_y, text)
        #print instance.__class__.__name__

        return instance

def __init__(self, pos_x=None, pos_y=None, size_x=None, size_y=None, text=None):
        print 'init'
        super(Vertex, self).__init__()

In the method of another class I have the call:

self.vertices[touch.uid] = Vertex(pos_x=self.bounds[3][0], pos_y=self.bounds[2][1], size_x=self.bounds[1][0] - self.bounds[3][0], size_y= self.bounds[0][1] - self.bounds[2][1], text=None)

which behaves as expected, and creates the Vertex() by calling both __new__() and __init__()

However, when I unpickle a Vertex() the __new__() method is called but not the __init__() method. I checked, and on unpickling the class of the instance is Vertex, so as far as I know __init__() should be called.

Upvotes: 1

Views: 966

Answers (1)

Martijn Pieters
Martijn Pieters

Reputation: 1122342

Unpickling deliberately does not call __init__ when reinstating an object. It creates a new 'empty' object (with __new__) then re-applies state to it.

You can customize this process by implementing either __getinitargs__ (to tell Pickle to call __init__ anyway, with given arguments) or to hook into __setstate__:

def __setstate__(self, state):
    self.__dict__.update(state)
    # do other things that need to be set on unpickling.

Upvotes: 2

Related Questions