Example for singleton decorator pattern in python

I know there is not very common in Python to use the singleton pattern, but I found a nice implementation of this pattern in Python 3 Patterns, Recipes and Idioms book. Starting with that example I implemented an equivalent of the well known PHP getConnection example.

You have the code below:

This is the class that implements the Singleton pattern.

[code language=”python”]
class Singleton:
def __init__(self, klass):
self.klass = klass
self.instance = None
def __call__(self, *args, **kwds):
if self.instance == None:
self.instance = self.klass(*args, **kwds)
return self.instance
[/code]

Now, we create a class and we decorate it with the Singleton class. Let’s import also MySQLdb module*.

[code language=”python”]
import MySQLdb

@Singleton
class Database:
connection = None
def get_connection(self):
if self.connection is None:
self.connection = MySQLdb.connect(host="localhost", user="root", passwd="razvan", db="mydatabase")
return self.connection
[/code]

Let’s test this:

[code language=”python”]
db1 = Database().get_connection()
db2 = Database().get_connection()

print (db2)
print (db1)
[/code]

You will see something like:

[code language=”bash”]
<_mysql.connection open to ‘localhost’ at 16b4800>
<_mysql.connection open to ‘localhost’ at 16b4800>
[/code]

As you can see there is only one object.

For fun, let’s remove the line “@Singleton” and re-run the example. This time you will see different objects:

[code language=”bash”]
<_mysql.connection open to ‘localhost’ at c91e20>
<_mysql.connection open to ‘localhost’ at bccba0>
[/code]

You can find the fully example here.

* If you don’t know how to install MySQLdb, you can check our previous post.

2 comments

  1. Cool. This makes a lot of sense in cases like this one where the singleton class’s constructor takes no args.

    But when the constructor does take arguments, I find it sketchy that this implementation will ignore the arguments that are passed to subsequent invocations of the class constructor and instead give you the singleton instance that was created with whatever args/ kwargs were used by the first person who constructed it.

    1. Hi,
      If I understood correctly your remarks:

      1. Of course you can pass arguments to the constructor:

      eg:
      @Singleton
      class Database:
      def __init__(self, dbname):
      self.dbname = dbname

      ….

      db1 = Database(‘my_database_name’).get_connection()

      2. I think that’s the idea of singleton. One instance (the first one) is used all the time across the system: “This is useful when exactly one object is needed to coordinate actions across the system. ” http://en.wikipedia.org/wiki/Singleton_pattern

Leave a comment

Your email address will not be published. Required fields are marked *