Can __new__ prevent __init__ from being called?

Martin ggrp1.20.martineau at dfgh.net
Wed Feb 16 16:40:24 EST 2005


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?
>
> I do not want to have any code in the __init__ method which checks if
> the instance is already initialized (like "if self.initialized:
return"
> at the beginning) because that would mean I'd have to insert this
> checking code in the __init__ method of every subclass.
>
> Is there an easier way than using a metaclass and writing a custom
> __call__ method?

Yes. You could move all your initalization logic from __init__ to a
separate init method and use the following simple recipe that does not
involve metaclasses and overriding __call__.

Although the base class __init__ does have to check to see if the
instance is initialized, you don't have to repeat the code in derived
classes:

class C(object):
    def __new__(cls, *args, **kwds):
        it = cls.__dict__.get("__it__")
        if it is not None:
            return it
        cls.__it__ = it = object.__new__(cls)
        it.init(*args, **kwds)
        return it

    def init(self, *args, **kwds):  # only called once
        print 'In C init.'
        pass

    def __init__(self):             # called each time
        print 'In C __init__.'

class D(C):
    def init(self, *args, **kwds):  # only called once
        print 'In D init.'
        pass

    def __init__(self):             # called each time
        print 'In D __init__.'

>>> C()
In C init.
In C __init__.

>>> C()
In C __init__.

>>> D()
In D init.
In D __init__.

>>> D()
In D __init__.

-Martin




More information about the Python-list mailing list