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.
[snip]
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