Can __new__ prevent __init__ from being called?
Jack Diederich
jack at performancedrivers.com
Tue Feb 15 18:27:59 EST 2005
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
More information about the Python-list
mailing list