[sugar] Re: Singleton

Ian Bicking ianb
Mon Aug 28 14:35:14 EDT 2006


Marco Pesenti Gritti <mpg <at> redhat.com> writes:
> Hi,
> 
> we should probably settle on a consistent implementation for singletons.
> 
> This is what we have in the ps:
> 
> _ps = None
> def get_instance():
>         global _ps
>         if not _ps:
>                 _ps = PresenceService()
>         return _ps
> 
> and PresenceService.get_instance() to get it.

If using this pattern, you should is "if _ps is None" and PresenceService 
should be named _PresenceService (because it is private).  If you don't need
to instantiate the object lazily, you should do:

  presence_service = _PresenceService()

at the module level, and then presence_service is the singleton (and you 
won't instantiate other instances unless you go out of your way to get the 
private class.

If you really want lazy instantiation, I prefer a factory function like
get_instance().

> In the icon cache:
> 
> class IconCache(gobject.GObject):
>     __metaclass__ = GObjectSingletonMeta
> 
> using this from sugar.util
> 
> class GObjectSingletonMeta(gobject.GObjectMeta):
>     """GObject Singleton Metaclass"""
> 
>     def __init__(klass, name, bases, dict):
>         gobject.GObjectMeta.__init__(klass, name, bases, dict)
>         klass.__instance = None
> 
>     def __call__(klass, *args, **kwargs):
>         if klass.__instance is None:
>             klass.__instance = gobject.GObjectMeta.__call__(klass, 
> *args, **kwargs)
>         return klass.__instance
> 
> and you can use the normal constructor.

The arguments get ignored if the singleton has already been created; that's 
no good.  Either there should be zero arguments, or it shouldn't be a 
singleton.  

Incidentally, you can also make a class a singleton (or instances unique 
based on the constructor parameters) by overriding __new__ (instead of the
metaclass's __call__), though I don't know if one is better than the other.  
The metaclass is probably better, because __new__ has some quirky behavior with
respect to __init__.

I personally don't care for the Borg pattern; module-level instantiation is
usually the right thing to do, and a factory function is very easy to 
understand otherwise.  Also, instances with a shared __dict__ are a little 
crazy.  Mostly singleton patterns involve over-design IMHO -- there's several
situations that call for different implementations, and all they have in 
common is that in some languages those different things are all implemented 
with singletons, even though that might not be appropriate in Python.

  Ian




More information about the Sugar-devel mailing list