How to use "__new__"?

Heiko Wundram modelnine at ceosg.de
Tue Mar 29 22:04:47 EST 2005


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.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 196 bytes
Desc: not available
URL: <http://mail.python.org/pipermail/python-list/attachments/20050330/eb08d43a/attachment.sig>


More information about the Python-list mailing list