Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python: thinking of a module and its variables as a singleton — Clean approach?

People also ask

Is Python module a singleton?

Modules are “singletons” in Python because import only creates a single copy of each module; subsequent imports of the same name keep returning the same module object.

What is a singleton Python?

A Singleton pattern in python is a design pattern that allows you to create just one instance of a class, throughout the lifetime of a program. Using a singleton pattern has many benefits. A few of them are: To limit concurrent access to a shared resource. To create a global point of access for a resource.

Is there a simple elegant way to define Singletons in Python?

Creating a singleton decorator (aka an annotation) is an elegant way if you want to decorate (annotate) classes going forward. Then you just put @singleton before your class definition.


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 variables
my_globals = {'foo': 'blah', 'bar':'stuff'}

# Functions that process the above variables
def 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'