[snip]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.
How can I prevent __init__ from being called on the already-initialized object?
The short answer: you can't:
http://www.python.org/2.2.3/descrintro.html#__new__
Note that in the Singleton example there, subclasses are told to override init, not __init__ for exactly this reason.
If it's okay that __init__ never be called, you could do something like:
py> class C(object): ... class __metaclass__(type): ... def __call__(cls, *args, **kwargs): ... return cls.__new__(cls, *args, **kwargs) ... instance = None ... def __new__(cls): ... if cls.instance is None: ... print 'Creating instance' ... cls.instance = object.__new__(cls) ... print 'Created' ... return cls.instance ... def __init__(self): ... print 'In init' ... py> C() Creating instance Created <__main__.C object at 0x011F2E30> py> C() <__main__.C object at 0x011F2E30>
If __init__ needs to be called, I might go with something like:
py> class C(object): ... class __metaclass__(type): ... def __call__(cls, *args, **kwargs): ... if cls.instance is None: ... print 'Creating instance' ... cls.instance = cls.__new__(cls, *args, **kwargs) ... print 'Created' ... cls.instance.__init__(*args, **kwargs) ... return cls.instance ... instance = None ... def __init__(self): ... print 'In init' ... py> C() Creating instance Created In init <__main__.C object at 0x011F2E50> py> C() <__main__.C object at 0x011F2E50>
where all the work is done in the metaclass and you don't even define __new__. I would probably also create the 'instance' attribute as part of the metaclass work, like:
py> class SingletonMetaclass(type): ... def __call__(cls, *args, **kwargs): ... try: ... return cls.__instance__ ... except AttributeError: ... cls.__instance__ = cls.__new__(cls, *args, **kwargs) ... cls.__instance__.__init__(*args, **kwargs) ... return cls.__instance__ ... py> class C(object): ... __metaclass__ = SingletonMetaclass ... def __init__(self): ... print '__init__' ... py> C() __init__ <__main__.C object at 0x011F3210> py> C() <__main__.C object at 0x011F3210> py> C() is C() True
But none of these solutions is particularly simple... Sorry!
STeVe -- http://mail.python.org/mailman/listinfo/python-list