Python: thinking of a module and its variables as a singleton — Clean approach?
A common alternative to using a module as a singleton is Alex Martelli's Borg pattern:
class Borg: __shared_state = {} def __init__(self): self.__dict__ = self.__shared_state # and whatever else you want in your class -- that's all!
There can be multiple instances of this class, but they all share the same state.
Maybe you can put all the variables in a global dict, and you can directly use the dict in your functions without "global".
# Singleton-related variablesmy_globals = {'foo': 'blah', 'bar':'stuff'}# Functions that process the above variablesdef work(some_parameter): if some_parameter: my_globals['bar'] = ... else: my_globals['foo'] = ...
why you can do it like this is Python Scopes and Namespaces.
One approach to implementing a singleton pattern with Python can also be:
have singleton __init()__
method raise an exception if an instance of the class already exists. More precisely, class has a member _single
. If this member is different from None
, exception is raised.
class Singleton: __single = None def __init__( self ): if Singleton.__single: raise Singleton.__single Singleton.__single = self
It could be argued that handling the singleton instance creation with exceptions is not very clean also. We may hide implementation details with a method handle()
as in
def Handle( x = Singleton ): try: single = x() except Singleton, s: single = s return single
this Handle()
method is very similar to what would be a C++ implementation of the Singleton pattern. We could have in Singleton
class the handle()
Singleton& Singleton::Handle() { if( !psingle ) { psingle = new Singleton; } return *psingle;}
returning either a new Singleton
instance or a reference to the existing unique instance of class Singleton
.
Handling the whole hierarchy
If Single1
and Single2
classes derive from Singleton
, a single instance of Singleton
through one of the derived class exists. This can be verify with this:
>>> child = S2( 'singlething' )>>> junior = Handle( S1)>>> junior.name()'singlething'