473,701 Members | 2,663 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

Can __new__ prevent __init__ from being called?

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.'
.... C() Creating instance.
Created.
In init.
<__main__.C object at 0x4062526c> C() In init. <---------- Here I want __init__ not to be executed.
<__main__.C object at 0x4062526c>


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.initialize d: 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?

--
Felix Wiemann -- http://www.ososo.de/
Jul 18 '05 #1
9 6211
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__(t ype):
.... 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__(t ype):
.... 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 SingletonMetacl ass(type):
.... def __call__(cls, *args, **kwargs):
.... try:
.... return cls.__instance_ _
.... except AttributeError:
.... cls.__instance_ _ = cls.__new__(cls , *args, **kwargs)
.... cls.__instance_ _.__init__(*arg s, **kwargs)
.... return cls.__instance_ _
....
py> class C(object):
.... __metaclass__ = SingletonMetacl ass
.... 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
Jul 18 '05 #2
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):
[snip] How can I prevent __init__ from being called on the already-initialized
object?


Is this an acceptable kludge?
class C(object): .... instance=None
.... def __new__(cls):
.... if C.instance is None:
.... print 'creating'
.... C.instance = object.__new__( cls)
.... else:
.... cls.__init__ = lambda self: None
.... return cls.instance
.... def __init__(self):
.... print 'in init'
.... a = C() creating
in init b = C()


(Translation: dynamically override now-useless __init__ method.
But if that works, why do you need __init__ in the first place?)

-Peter
Jul 18 '05 #3
Peter Hansen wrote:
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):

[snip]
How can I prevent __init__ from being called on the already-initialized
object?

Is this an acceptable kludge?
>>> class C(object): ... instance=None
... def __new__(cls):
... if C.instance is None:
... print 'creating'
... C.instance = object.__new__( cls)
... else:
... cls.__init__ = lambda self: None
... return cls.instance
... def __init__(self):
... print 'in init'
... >>> a = C() creating
in init >>> b = C()
>>>
(Translation: dynamically override now-useless __init__ method.
But if that works, why do you need __init__ in the first place?)

-Peter

Or this one: use an alternative constructor:

class C(object):
instance = None
@classmethod
def new(cls, *args, **kw):
if cls.instance is None:
print 'Creating instance.'
cls.instance = object.__new__( cls)
print 'Created.'
cls.instance.__ init__(*args,** kw)
return cls.instance
def __init__(self):
print 'In init.'
c = C.new() Creating instance.
Created.
In init. c = C.new()


Michael

Jul 18 '05 #4
Steven Bethard wrote:
Felix Wiemann wrote:
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__


What a pity. By the way, I'm just seeing that the web page says:

| If you return an existing object, the constructor call will still call
| its __init__ method. If you return an object of a different class, its
| __init__ method will be called.

However, the latter doesn't seem to be true, or am I missing something?
class A(object): .... def __init__(self):
.... print 'Init of A.'
.... instance = A() Init of A. class B(object): .... def __new__(self):
.... return instance
.... def __init__(self):
.... print 'Init of B.'
.... B() # <--------- A's __init__ is *not* called. <__main__.A object at 0x4062424c> instance = object.__new__( B)
B() # <--------- B's __init__ is called

Init of B.
<__main__.B object at 0x406243ec>

So there seems to be some type-checking in type.__call__.
Note that in the Singleton example there, subclasses are told to
override init, not __init__ for exactly this reason.
I see.
py> class C(object):
... class __metaclass__(t ype):
... 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
I didn't think of inlining the metaclass; that's really nice.
[...] where all the work is done in the metaclass and you don't even
define __new__.


Yeah, that's good. I think I'll go that way.

Thanks a lot!

--
Felix Wiemann -- http://www.ososo.de/
Jul 18 '05 #5
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.Ap pContext):
"""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.in it(*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.AppCont ext.__init__(se lf, req)
# lots of initialization done here
return

Page is a singleton but it inherits from the class context.AppCont ext
which is just a regular class. The empty Page.__init__ doesn't call
the context.AppCont ext.__init__ but the once-only Page.init does.

Hope that helps,

-Jack
Jul 18 '05 #6
Felix Wiemann wrote:
Steven Bethard wrote:

Felix Wiemann wrote:

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__

[snip]
This prompts a similar query. __new__ appears to be intended for
immutable objects but it seems to be called as part of constructor
process for all instances.

Regarding the original question. It is not possible to prevent the use
of __init__ but is it possible to prevent __init__ having any effect by
setting a flag when __init__ is called for the first creation of the
instance.

Colin W.

Jul 18 '05 #7
Colin J. Williams wrote:
This prompts a similar query. __new__ appears to be intended for
immutable objects but it seems to be called as part of constructor
process for all instances.


That's because Python has no builtin way of determining whether or not a
given type is immutable. If you wanted to, you could define both
__new__ and __init__, the first to set immutable parts and the second to
set mutable parts, e.g.:

py> class PartlyMutableTu ple(tuple):
.... def __new__(cls, *args, **kwargs):
.... return super(PartlyMut ableTuple, cls).__new__(cl s, args)
.... def __init__(self, *args, **kwargs):
.... self.__dict__.u pdate(kwargs)
....
py> t = PartlyMutableTu ple(1, 2, 3, a=4, b=5)
py> t
(1, 2, 3)
py> t.a, t.b
(4, 5)
py> t.a, t.b = t.b, t.a
py> t.a, t.b
(5, 4)
py> t[0] = 2
Traceback (most recent call last):
File "<interacti ve input>", line 1, in ?
TypeError: object does not support item assignment

I don't think I'd advise this strategy, but by always calling both
__new__ and __init__, Python makes it possible...

Steve
Jul 18 '05 #8
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.initialize d: 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__.ge t("__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

Jul 18 '05 #9
I meant to say:

Although the base class __new__ does have to check to see if the
^^^^^^^
instance is initialized, ...

not:
Although the base class __init__ does have to check to see if the
instance is initialized, ...


Jul 18 '05 #10

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

2
1485
by: Uwe Mayer | last post by:
Hi, I want to create a copy of an object from out of its base class: class A(object): def copy(self): .... class B(A): ....
3
1928
by: Christoph Groth | last post by:
-----BEGIN PGP SIGNATURE----- Version: GnuPG v1.0.6 (GNU/Linux) Comment: For info see http://www.gnupg.org iD8DBQBAJmKufx2/njzvX5URAipnAKCUco5ZCl85xJ8YboHHJM3RBIqiGwCfX3/P tL1uWVMKntHThZ550BS32aw= =4Ijl -----END PGP SIGNATURE-----
2
1488
by: Steven Bethard | last post by:
Felix Wiemann wrote: > Steven Bethard wrote: >> http://www.python.org/2.2.3/descrintro.html#__new__ > > > I'm just seeing that the web page says: > > | If you return an existing object, the constructor call will still > | call its __init__ method. If you return an object of a different
3
2602
by: James Stroud | last post by:
Hello All, I'm running 2.3.4 I was reading the documentation for classes & types http://www.python.org/2.2.3/descrintro.html And stumbled on this paragraph: """ __new__ must return an object. There's nothing that requires that it return a
5
2156
by: Ken Schutte | last post by:
Hi, I'm been trying to create some custom classes derived from some of python's built-in types, like int and list, etc. I've run into some trouble, which I could explain with a couple simple examples. Lets say I want an int-derived class that is initilized to one greater than what it's constructor is given: class myint(int): def __new__(cls, intIn):
1
1198
by: Frank Benkstein | last post by:
Hi, the behaviour I always observed when creating instances by calling the class A is that '__init__' is always only called when the object returned by A.__new__ is an instance of A. This can be observed by the following code: class A(object): def __new__(cls, *args, **kwds): print "A.__new__", args, kwds
5
1462
by: Sandra-24 | last post by:
Ok here's the problem, I'm modifying a 3rd party library (boto) to have more specific exceptions. I want to change S3ResponseError into about 30 more specific errors. Preferably I want to do this by changing as little code as possible. I also want the new exceptions to be a subclass of the old S3ResponseError so as to not break old code that catches it. If I meet these two requirements I expect my modification to make it into boto and then...
4
3540
by: Steven D'Aprano | last post by:
When you call a new-style class, the __new__ method is called with the user-supplied arguments, followed by the __init__ method with the same arguments. I would like to modify the arguments after the __new__ method is called but before the __init__ method, somewhat like this: .... def __new__(cls, *args): .... print "__new__", args
3
2767
by: Torsten Mohr | last post by:
Hi, i have some questions related to new style classes, they look quite useful but i wonder if somebody can give me an example on constructors using __new__ and on using __init__ ? I just see that when using it i can't give parameters to __new__ and when i additionally define __init__ then __new__ is not called.
0
8732
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However, people are often confused as to whether an ONU can Work As a Router. In this blog post, we’ll explore What is ONU, What Is Router, ONU & Router’s main usage, and What is the difference between ONU and Router. Let’s take a closer look ! Part I. Meaning of...
0
8649
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can effortlessly switch the default language on Windows 10 without reinstalling. I'll walk you through it. First, let's disable language synchronization. With a Microsoft account, language settings sync across devices. To prevent any complications,...
0
9082
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven tapestry of website design and digital marketing. It's not merely about having a website; it's about crafting an immersive digital experience that captivates audiences and drives business growth. The Art of Business Website Design Your website is...
0
7822
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing, and deployment—without human intervention. Imagine an AI that can take a project description, break it down, write the code, debug it, and then launch it, all on its own.... Now, this would greatly impact the work of software developers. The idea...
0
5904
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and then checking html paragraph one by one. At the time of converting from word file to html my equations which are in the word document file was convert into image. Globals.ThisAddIn.Application.ActiveDocument.Select();...
0
4410
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The last exercise I practiced was to create a LAN-to-LAN VPN between two Pfsense firewalls, by using IPSEC protocols. I succeeded, with both firewalls in the same network. But I'm wondering if it's possible to do the same thing, with 2 Pfsense firewalls...
1
3102
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated we have to send another system
2
2398
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.
3
2035
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence can significantly impact your brand's success. BSMN Consultancy, a leader in Website Development in Toronto offers valuable insights into creating effective websites that not only look great but also perform exceptionally well. In this comprehensive...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.