Upload
violeta-boullosa
View
17
Download
0
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