Singleton Class Exception

Jason tenax.raccoon at gmail.com
Mon Nov 13 13:30:47 EST 2006


I threw together two different singleton classes.  They both ensure
that the initializers and destructors can be called at most once.  (The
ImmortalSingleton won't ever have its destructor called unless the
programmer manually forces things.)

I haven't extensively tested these things, so handle this code like a
rabid wildebeest.  Observe that Python may not call your destructors
when you expect.  IAnd again, you probably want the Borg pattern.

Still, this was an interesting exercise to do.

--- Code Starts ---
class MortalSingleton(object):
    """This class implements a 'mortal' singleton pattern.  Classes
derived
from this class cannot be directly instantiated or take arguments in
their
initializers.

The GetSingleton() class method returns a reference to a single
instance,
or creates a single instance as needed.

This class only keeps a weak reference to the single instance.  This
means
that, if all hard references are destroyed, the instance can be
destroyed
by Python (and the __del__ method *could* be called, depending on
implementation).  Thus, the single-ton is mortal.

This could be used as a mix-in class, assuming that the other classes
do not over-ride the __new__() method (which prevents willy-nilly
instantiation).

Note that if you need all instances to share state, you probably want
to use the Borg pattern.

Comments on this travesty are appreciated.  *grin*
"""
    def __new__(cls, *args, **keyargs):
        # Raise a run-time error preventing direct instantiation
        raise RuntimeError(
            'Do not instantiate %s directly.  Use the
%s.GetSingleton()'
            'class method.' % (cls.__name__, cls.__name__)
            )

    @classmethod
    def GetSingleton(cls):
        from weakref import ref

        retObject = getattr(cls, '_instance', lambda : None)()
        if retObject is None:
            # Create a new object with the given class
            retObject = object.__new__(cls)

            # The initializer must be manually called in this case
            retObject.__init__()
            cls._instance = ref(retObject)
        return retObject

class ImmortalSingleton(object):
    """This class implements a classic 'immortal' singleton pattern.
Classes derived from this class will allow only one instance to exist.

Since the class caches a hard reference to the single pattern, it
doesn't die unless the programmer gets rid of all references and
manually
deletes the cache reference.

Note that you probably want to use a variant of the Borg class rather
than
this."""
    def __new__(cls, *args, **keyargs):
        # Raise a run-time error preventing direct instantiation

        raise RuntimeError(
            'Do not instantiate %s directly.  Use the
%s.GetSingleton()'
            'class method.' % (cls.__name__, cls.__name__)
            )

    @classmethod
    def GetSingleton(cls):
        retObject = getattr(cls, '_instance', lambda : None)()
        if retObject is None:
            # Create a new object with the given class
            retObject = object.__new__(cls)

            # The initializer must be manually called in this case
            retObject.__init__()
            cls._instance = retObject
        return retObject




More information about the Python-list mailing list