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