classes
Michele Simionato
mis6 at pitt.edu
Mon Jul 21 08:51:16 EDT 2003
Steven Taschuk <staschuk at telusplanet.net> wrote in message news:<mailman.1058723911.12956.python-list at python.org>...
> For the particular problem you're interested in -- singletons --
> here are a few approaches:
>
> First, use __new__ trickery:
>
> _the_instance = None
> class MySingleton(object):
> def __new__(self):
> global _the_instance
> if _the_instance is None:
> _the_instance = object.__new__(self)
> return _the_instance
Why are you using a global here and not something like
class MySingleton(object):
_the_instance = None
def __new__(cls):
if cls._the_instance is None:
cls._the_instance = object.__new__(self)
return cls._the_instance
?
> Example use:
>
> >>> x = MySingleton()
> >>> y = MySingleton()
> >>> x is y # same object!
> True
>
> In this approach, users create instances of MySingleton as they
> would for any other class (rather than by calling a getInstance
> classmethod) -- that action just happens to return the same object
> always.
>
> One gotcha with this approach can be observed by adding
>
> def __init__(self):
> print 'running __init__ on instance %s' % id(self)
>
> Then we see
>
> >>> x = MySingleton()
> running __init__ on instance 1075795852
> >>> y = MySingleton()
> running __init__ on instance 1075795852
> >>> x is y
> True
>
> As shown, each "instantiation" runs __init__ on the single
> instance again. If you have initialization which should occur
> only when the single instance is actually created:
>
> _the_instance = None
> class MySingleton(object):
> def __new__(self):
> global _the_instance
> if _the_instance is None:
> _the_instance = object.__new__(self)
> _the_instance._my_init()
> return _the_instance
> def _my_init(self):
> pass # one-time initialization here
>
> (Another possible issue with this approach arises when subclassing
> MySingleton. Details left as an exercise.)
>
> Second approach: Use a metaclass. See
> <http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/102187>
Unfortunately, I see that this recipe is not very recommendable. I have
just submitted a fix which seems to work:
class Singleton(type):
def __init__(cls,name,bases,dic):
super(Singleton,cls).__init__(name,bases,dic)
cls.instance=None
def __call__(cls,*args,**kw):
if cls.instance is None:
cls.instance=super(Singleton,cls).__call__(*args,**kw)
return cls.instance
Here is how it works under inheritance and avoids the problem with
calling __init__ twice:
class C:
__metaclass__=Singleton
def __init__(self):
print "C: initializing ",self
class D(C):
def __init__(self):
print "D: initializing ",self
c1=C() # => C: initializing <__main__.C object at 0x4031c0ac>
c2=C() # no output
d=D() # D: initializing <__main__.D object at 0x4031c02c>
print c1 is c2 # => yes
> Third: forget about singletons and use a Borg. See
> <http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/66531>
> (With Borgs, multiple instances may exist, but they share state.)
>
> Fourth: rethink the idea that a database connection should be a
> singleton. See
> <http://c2.com/cgi/wiki?SingletonsAreEvil>
> and linked pages for discussion on the merits of singletons.
HTH,
Michele
More information about the Python-list
mailing list