On Tue, Feb 15, 2005 at 10:30:21PM +0100, Felix Wiemann wrote: > Sometimes (but not always) the __new__ method of one of my classes > returns an *existing* instance of the class. However, when it does > that, the __init__ method of the existing instance is called > nonetheless, so that the instance is initialized a second time. For > example, please consider the following class (a singleton in this case): > > >>> class C(object): > ... instance = None > ... def __new__(cls): > ... if C.instance is None: > ... print 'Creating instance.' > ... C.instance = object.__new__(cls) > ... print 'Created.' > ... return cls.instance > ... def __init__(self): > ... print 'In init.' > ... <snip> > How can I prevent __init__ from being called on the already-initialized > object? <snip> > Is there an easier way than using a metaclass and writing a custom > __call__ method?
The standard recipe is to define an alternate init method and call it once when you instantiate the object (I couldn't find it on ASPN though). Here is a cut-n-paste from production code. The work normally done in the magic __init__() is done in init() instead. class Page(context.AppContext): """the One True Singleton """ _single = None # our singleton reference def __new__(cls, *args, **opts): if (Page._single is None): Page._single = object.__new__(cls) Page._single.init(*args, **opts) return Page._single def __init__(self, *args, **opts): """We are a singleton, so setup is done just once in init() because __init__() will be called every time the singleton is re-issued This __init__ just prevents our parent's __init__'s from running other than when told to by our init() """ return def init(self, req = None): """setup Db objects, cgi params etc Here is also where we decide if we are being run from the command line or in mod_python""" context.AppContext.__init__(self, req) # lots of initialization done here return Page is a singleton but it inherits from the class context.AppContext which is just a regular class. The empty Page.__init__ doesn't call the context.AppContext.__init__ but the once-only Page.init does. Hope that helps, -Jack -- http://mail.python.org/mailman/listinfo/python-list