How to use "__new__"?

C

could ildg

As there is already __init__, why need a __new__?
What can __new__ give us while __init__ can't?
In what situations we should use __new__?
And in what situations we must use __new__?
Can __new__ take the place of __init__?
Thanks.
 
S

Steven Bethard

could said:
As there is already __init__, why need a __new__?
What can __new__ give us while __init__ can't?
In what situations we should use __new__?
And in what situations we must use __new__?
Can __new__ take the place of __init__?

I believe the current documentation will be updated when 2.4.1 is
released, but documentation for __new__ is now available at:

http://www.python.org/dev/doc/devel/ref/customization.html

In short, you could use __new__ in place of __init__, but it's probably
only useful to do so if you need to change an instance *before* it's
created. In general, if you aren't subclassing an immutable type, and
you're not sure that you need __new__, you probably don't.

STeVe
 
C

could ildg

Thank you.
I'm clear after I read the doc:
If __new__() returns an instance of cls, then the new instance's
__init__() method will be invoked like "__init__(self[, ...])", where
self is the new instance and the remaining arguments are the same as
were passed to __new__().

If __new__() does not return an instance of cls, then the new
instance's __init__() method will not be invoked.

__new__() is intended mainly to allow subclasses of immutable types
(like int, str, or tuple) to customize instance creation.
 
H

Heiko Wundram

Am Mittwoch, 30. März 2005 03:27 schrieb could ildg:
Thank you.
I'm clear after I read the doc:
If __new__() returns an instance of cls, then the new instance's
__init__() method will be invoked like "__init__(self[, ...])", where
self is the new instance and the remaining arguments are the same as
were passed to __new__().

If __new__() does not return an instance of cls, then the new
instance's __init__() method will not be invoked.

__new__() is intended mainly to allow subclasses of immutable types
(like int, str, or tuple) to customize instance creation.

Remember that __new__() can also be used to create singletons (to return a
pre-existing instance in case some form of argument matches, for example):

class Singleton(object):
__buffer = {}

def __new__(cls,somearg):
if somearg not in cls.__buffer:
cls.__buffer[somearg] = super(cls,Singleton).__new__(cls)
return cls.__buffer[somearg]

def __init__(self,somearg):
self.__somearg = somearg

def __repr__(self):
False

You could extend the above example quite easily to deal with deallocation (a
reference to each created singleton is retained using the above class,
always, as long as the program is running) and also to make it threadsafe or
to disable initialization in case the singleton has already been initialized
before.

--
--- Heiko.

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.1 (GNU/Linux)

iD8DBQBCShCbf0bpgh6uVAMRAqhqAJ4heiYC24zpnGC0Vp9dKU4exN3DJgCdGPtB
IteiPzZBBumSXSw6M/VcmYs=
=ew0P
-----END PGP SIGNATURE-----
 
H

Heiko Wundram

Am Mittwoch, 30. März 2005 04:36 schrieb Heiko Wundram:
You could extend the above example quite easily to deal with deallocation
(a reference to each created singleton is retained using the above class,
always, as long as the program is running) and also to make it threadsafe
or to disable initialization in case the singleton has already been
initialized before.

Just to post a complete example of a Singleton class which works in a
multithreaded environment, and allows you to update future instances (a
sample, untested implementation):

<code>
import threading
import weakref

class SingletonBase(object):
__buffer = {}
__bufferLock = threading.RLock()

def __new__(cls,*args,**kwargs):
cls.__bufferLock.acquire()
try:
inst = cls.__create_new__(buffer,*args,**kwargs)
if not hasattr(inst,"_SingletonBase__instanceLock"):
inst.__instanceLock = threading.RLock()
inst.__initialized = False
return inst
finally:
cls.__bufferLock.release()

@classmethod
def __create_new__(cls,*args,**kwargs):
return super(SingletonBase,cls).__new__(cls)

def __init__(self,*args,**kwargs):
self.__instanceLock.acquire()
try:
if not self.__initialized:
self.__initialize_new__(*args,**kwargs)
self.__initialized = True
else:
self.__update_old__(*args,**kwargs)
finally:
self.__instanceLock.release()

def __initialize_new__(self,*args,**kwargs):
pass

def __update_old__(self,*args,**kwargs):
pass

class Singleton(SingletonBase):

@classmethod
def __create_new__(cls,buffer,somearg):
inst = buffer.get(somearg,lambda: None)()
if inst is None:
inst = super(Singleton,cls).__create_new__(cls)
buffer[somearg] = weakref.ref(inst)
return inst

def __initialize_new__(self,somearg):
print "Initializing new instance."
self.__somearg = somearg

def __update_old__(self,somearg):
print "Updating old."
assert somearg == self.__somearg

# Initialize three singletons.
print "Creating singletons for 1, 2, 1."
x = Singleton(1)
y = Singleton(2)
z = Singleton(1)

# Print them out.
print "\nThree singletons: x, y, z."
print repr(x)
print repr(y)
print repr(z)

# Assert that x is not y, and x is z.
print "\nx is y, x is z"
print x is y
print x is z

# Delete names, and make sure weakrefs are unbound.
print "\nRemove all three singletons."
del x
del y
del z

# Recreate singleton for value 1.
print "\nRecreating singleton for value 1."
x = Singleton(1)
y = Singleton(1)

# Print them out.
print "\nNew Singleton(1): x, y."
print repr(x)
print repr(y)

# Check that x is y.
print "\nx is y"
print x is y
</code>

The above program prints the following output when run:

<output>
Creating singletons for 1, 2, 1.
Initializing new instance.
Initializing new instance.
Updating old.

Three singletons: x, y, z.
<__main__.Singleton object at 0xb7bfbc6c>
<__main__.Singleton object at 0xb7bfbcac>
<__main__.Singleton object at 0xb7bfbc6c>

x is y, x is z
False
True

Remove all three singletons.

Recreating singleton for value 1.
Initializing new instance.
Updating old.

New Singleton(1): x, y.
<__main__.Singleton object at 0xb7bfbc6c>
<__main__.Singleton object at 0xb7bfbc6c>

x is y
True
</output>

HTH!

--
--- Heiko.

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.1 (GNU/Linux)

iD8DBQBCShdSf0bpgh6uVAMRAmIMAJ9EzsSRebvDog6tixm3MEp3OXBDngCbB6Eu
OYud8wmgcKUyODedkrW4PAQ=
=P8Nt
-----END PGP SIGNATURE-----
 
T

Terry Reedy

could ildg said:
__new__() is intended mainly to allow subclasses of immutable types
(like int, str, or tuple) to customize instance creation.

Exactly. It is an anwer to the conundrum: How do you give an immutable
object its unchangeable value. It is much like how to move an unmovable
object to its permanent position ;-).

TJR
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
474,230
Messages
2,571,161
Members
47,796
Latest member
AlphonseNa

Latest Threads

Top