The Singleton Pattern Implemented With Python « Python Recipes « ActiveState Code

Embed Size (px)

Citation preview

  • 28/4/2014 The Singleton Pattern implemented with Python Python recipes ActiveState Code

    http://code.activestate.com/recipes/52558-the-singleton-pattern-implemented-with-python/ 1/8

    Python,42lines

    TheSingletonPatternimplementedwithPython(Pythonrecipe)byJrgenHermannActiveStateCode(http://code.activestate.com/recipes/52558/)

    1

    Thefollowingclassshowshowtoimplementthesingletonpattern[1]inPython.Asingletonisaclassthatmakessureonlyoneinstanceofitisevercreated.Typicallysuchclassesareusedtomanageresourcesthatbytheirverynaturecanonlyexistonce.

    1 2 3 4 5 6 7 8 9101112131415161718192021222324252627282930313233343536373839404142

    class Singleton: """ A python singleton """

    class __impl: """ Implementation of the singleton interface """

    def spam(self): """ Test method, return singleton id """ return id(self)

    # storage for the instance reference __instance = None

    def __init__(self): """ Create singleton instance """ # Check whether we already have an instance if Singleton.__instance is None: # Create and remember instance Singleton.__instance = Singleton.__impl()

    # Store instance reference as the only member in the handle self.__dict__['_Singleton__instance'] = Singleton.__instance

    def __getattr__(self, attr): """ Delegate access to implementation """ return getattr(self.__instance, attr)

    def __setattr__(self, attr, value): """ Delegate access to implementation """ return setattr(self.__instance, attr, value)

    # Test its1 = Singleton()print id(s1), s1.spam()

    s2 = Singleton()print id(s2), s2.spam()

    # Sample output, the second (inner) id is constant:# 8172684 8176268# 8168588 8176268

    Thisimplementationhidesthesingletoninterfaceinaninnerclassandcreatesexactlyoneinstanceoftheinnerclass.Theouterclassisahandletotheinnerclassand

  • 28/4/2014 The Singleton Pattern implemented with Python Python recipes ActiveState Code

    http://code.activestate.com/recipes/52558-the-singleton-pattern-implemented-with-python/ 2/8

    delegatesanyrequeststoit.Whiletheid()ofthehandleobjectschanges,theid()oftheinnerclasswhichimplementsthesingletonbehaviourisconstant.

    Ofcourse,theinnerclassisnotREALLYhidden,likeanythinginPython.Butyouhavetoinvestextraefforttobreakintothesingleton.

    Thisisrelatedtothe"Automaticdelegationasanalternativetoinheritance"recipe.

    [1]Gamma,Helm,etal,"DesignPatternsElementsofReusableObjectOrientedSoftware".AddisonWesley,1995,ISBN0201633612.

    Tags:oop

    13comments

    HrissimirNeikov 13yearsagoRE:Singletonrightbehavior.allid'sinthesampleoutputmustbeequal!

    Trythis:

    class A:

    # attribute known to function Singleton

    _instance = None

    def foo(self):

    return id(self)

    def Singleton(klass):

    if not klass._instance:

    klass._instance = klass()

    return klass._instance

    # subclass A

    class B(A):

    pass

  • 28/4/2014 The Singleton Pattern implemented with Python Python recipes ActiveState Code

    http://code.activestate.com/recipes/52558-the-singleton-pattern-implemented-with-python/ 3/8

    b = Singleton(A)

    c = Singleton(B)

    d = Singleton(A)

    print id(b),b.foo()

    print id(c),c.foo()

    print id(d),c.foo()

    # Output:

    7963404 7963404

    7963404 7963404

    7963404 7963404

    mattkangas 12years,10monthsagoAsimplersingleton.Phooey,bothoftheseexamplesaretoocomplicated.:)

    class _Spam: def __call__(self): return self

    Spam = _Spam()del _Spam

    Alas,thisisn'tperfect.IfforsomereasonyouneedtosubclassSpam,youobviouslycan't.ButIthinkthisissufficientformostpeople'sneeds.

    SincePythondoesn'thaveanynotionofclass/staticmethods,itisn'tpossibletobuildsingletons"therightway".Everyworkablesolutionwillbeacompromiseofsomesort.

    mattkangas 12years,10monthsagoObfuscatedsingleton.ps:Ofcoursethisispossibletoo...

    class Spam: def __call__(self): return self

    Spam = Spam()

  • 28/4/2014 The Singleton Pattern implemented with Python Python recipes ActiveState Code

    http://code.activestate.com/recipes/52558-the-singleton-pattern-implemented-with-python/ 4/8

    RowlandSmith 12years,8monthsagoSingletonexample.

    class TestSingleton :

    # Create a class variable that will hold a reference # to the single instance of TestSingleton.

    instance = None

    # Define a helper class that will override the __call___ # method in order to provide a factory method for TestSingleton.

    class TestSingletonHelper :

    def __call__( self, *args, **kw ) :

    # If an instance of TestSingleton does not exist, # create one and assign it to TestSingleton.instance.

    if TestSingleton.instance is None : object = TestSingleton() TestSingleton.instance = object

    # Return TestSingleton.instance, which should contain # a reference to the only instance of TestSingleton # in the system.

    return TestSingleton.instance

    # Create a class level method that must be called to # get the single instance of TestSingleton.

    getInstance = TestSingletonHelper()

    # Initialize an instance of the TestSingleton class.

    def __init__( self ) :

    # Optionally, you could go a bit further to guarantee # that no one created more than one instance of TestSingleton:

    if not TestSingleton.instance == None : raise RuntimeError, 'Only one instance of TestSingleton is allowed!'

    #Continiue initialization...

  • 28/4/2014 The Singleton Pattern implemented with Python Python recipes ActiveState Code

    http://code.activestate.com/recipes/52558-the-singleton-pattern-implemented-with-python/ 5/8

    # Test this implementation of the Singleton pattern. All of the# references printed out should have the same address.

    for i in range( 10 ) : print TestSingleton.getInstance()

    # This call should raise a RuntimeError indicating# that a single instance of TestSingleton already exists.

    TestSingleton()

    Thissingletonimplementationdrawsfrom'staticmethod/classmethod'

    examplesbyThomasHellerandClarkEvans.

    SbastienBigaret 11years,11monthsagoSubclassingispossible,butugly!InheritanceispossibleandcanbedocumentedassuchifyouusesuchanidiomtoimplementtheSingleton.

    class Eggs(Spam.__class__): # The original class is still available def __call__(self): # These 3 lines return self # should beEggs=Eggs() # replicated

    SbastienBigaret 11years,11monthsagoSmallcorrection.Thisdoesonlyworkifyoucall'getInstance()'beforetheconstructorifnot,youwillgetamuchdifferentinstancesasyouwishuntil'getInstance()'getcalled:

    >>> for i in range(3):>>> print '> %s'%TestSingleton()

    > > >

    Ifyouwanttomakesurethattheconstructorisnotcalledmorethanonce,'TestSingleton.__init__'shouldread:

    def __init__(self): if not TestSingleton.instance == None : raise RuntimeError, 'Only one instance of TestSingleton is allowed!' TestSingleton.instance=self

    (lastlineadded)

  • 28/4/2014 The Singleton Pattern implemented with Python Python recipes ActiveState Code

    http://code.activestate.com/recipes/52558-the-singleton-pattern-implemented-with-python/ 6/8

    ChristianMeyer 7years,5monthsagoMucheasiersolution.Ifoundsomeofthepreviouslymentionedideasabittoocomplicated.Here'smyimplementation:

    class _Singleton(object):

    def __init__(self): # just for the sake of information self.instance = "Instance at %d" % self.__hash__()

    _singleton = _Singleton()

    def Singleton(): return _singleton

    =====

    >>> from singleton import Singleton>>> s1 = Singleton()>>> s2 = Singleton()>>> s1.instance'Instance at -1226695220'>>> s2.instance'Instance at -1226695220'>>> s1 == s2True

    MarcSantiago 6years,5monthsagoSingletonswithinheritance.

    class Singleton(object): __single = None # the one, true Singleton

    def __new__(classtype, *args, **kwargs): # Check to see if a __single exists already for this class # Compare class types instead of just looking for None so # that subclasses will create their own __single objects if classtype != type(classtype.__single): classtype.__single = object.__new__(classtype, *args, **kwargs) return classtype.__single

    def __init__(self,name=None): self.name = name

    def display(self):

  • 28/4/2014 The Singleton Pattern implemented with Python Python recipes ActiveState Code

    http://code.activestate.com/recipes/52558-the-singleton-pattern-implemented-with-python/ 7/8

    print self.name,id(self),type(self)

    class Subsingleton(Singleton): pass

    if __name__ == "__main__": o1 = Singleton('foo') o1.display() o2 = Singleton('bar') o2.display() o3 = Subsingleton('foobar') o3.display() o4 = Subsingleton('barfoo') o4.display() print 'o1 = o2:',o1 == o2 print 'o1 = o3:',o1 == o3 print 'o3 = o4:',o3 == o4 print 'o1 is a singleton?',isinstance(o1,Singleton) print 'o3 is a singleton?',isinstance(o3,Singleton) print 'o1 is a subsingleton?',isinstance(o1,Subsingleton) print 'o3 is a subsingleton?',isinstance(o3,Subsingleton)

    YairChuchem 6years,1monthagogoodone.youshouldputthatoneasarecipe.

    AlanFelice 6yearsagoAndwhataboutthreads?GivenimplementationsofSingletonpatternaren'tthreadsafe.

    Somemorestuffisneededtoreachthatpoint.Somethinglikethe

    followingshouldbeused:

    class MySingletonClass(object): '''Implement Pattern: SINGLETON'''

    __lockObj = thread.allocate_lock() # lock object __instance = None # the unique instance

    def __new__(cls, *args, **kargs): return cls.getInstance(cls, *args, **kargs)

    def __init__(self): pass

    def getInstance(cls, *args, **kargs): '''Static method to have a reference to **THE UNIQUE** instance''' # Critical section start

  • 28/4/2014 The Singleton Pattern implemented with Python Python recipes ActiveState Code

    http://code.activestate.com/recipes/52558-the-singleton-pattern-implemented-with-python/ 8/8

    cls.__lockObj.acquire() try: if cls.__instance is None: # (Some exception may be thrown...) # Initialize **the unique** instance cls.__instance = object.__new__(cls, *args, **kargs)

    '''Initialize object **here**, as you would do in __init__()...'''

    finally: # Exit from critical section whatever happens cls.__lockObj.release() # Critical section end

    return cls.__instance getInstance = classmethod(getInstance)

    GaryRobinson 4years,9monthsagoThere'saversionthat'sbeenevolvingforabout5yearsathttp://www.garyrobinson.net/2004/03/python_singleto.html.It'sprettycompleteandhasbenefittedfromafairamountoffeedbackandsuggestionsatthatlocation.It'sthreadsafeandincludesunittests.

    Itriedtopostithere,butevenleavingouttheunittests,it'slongerthanthe3000charlimitinthiscommentarea.

    GaryRobinson 4years,9monthsagoOops,thesourceatthelinkabovewasaccidentallyanoutofdateversionuntilnow(withoutthethreadsafetyandsomeotherimprovements)untilnow.Fixednow.

    Reorx 1year,6monthsagoCode:

    class Singleton(object): @classmethod def instance(cls, *args, **kwgs): if not hasattr(cls, "_instance"): cls._instance = cls(*args, **kwgs) return cls._instance