5

Recently, I am considering how to implement a Singleton pattern in Python. The following code works fine if the Singleton class has no subclasses.

class Singleton(object):
    _instance = None

    def __new__(cls, *args, **kwargs):
        if cls._instance is None:
            cls._instance = super(Singleton, cls).__new__(cls, *args, **kwargs)
        return cls._instance

However, the Singleton class may have subclasses.

class SingletonSub1(Singleton):
    def __new__(cls, *args, **kwargs):
        return super(SingletonSub1, cls).__new__(cls, *args, **kwargs)

class SingletonSub2(Singleton):
    def __new__(cls, *args, **kwargs):
        return super(SingletonSub1, cls).__new__(cls, *args, **kwargs)

The requirement is that you can have only 1 instance in the system which is Singleton, SingletonSub1, or SingletonSub2. How can I implement this? I know I can definitely use a module level variable to hold the Singleton object. But it is really a bad code...

Wei
  • 191
  • 3
  • 13
  • 1
    This seems like a bad idea. You want a Singleton, but it can be one of 3 things? Could you add a little more information on the _motivation_ behind doing this? – DaoWen Jan 25 '14 at 21:49
  • 4
    Short answer - you don't. One commonly repeated statement about Python is "we're all consenting adults here." Don't try to restrict what people can do with your classes (e.g. how many instances they create of one class) - just make sure you tell them what they _should_ do. If they do something you have recommended that they don't do and stuff goes wrong then it is their own fault. – rlms Jan 25 '14 at 21:49
  • There is an example in the design pattern text book which is about a MazeFactory Singleton object. The MazeFactory has two subclasses BombedMazeFactory and EnchantedMazeFactory. An application can only have 1 maze factory object which can be any of the above three. C++ implementation can enforce this restriction. But I don't know how Python can do this. – Wei Jan 25 '14 at 21:53
  • 1
    Take look at the answers to ["Creating a singleton in python"](http://stackoverflow.com/q/6760685/2419207) or just ["share global variables across modules"](http://effbot.org/pyfaq/how-do-i-share-global-variables-across-modules.htm) – iljau Jan 25 '14 at 22:02
  • If you want to create independent singleton classes, I suggest you use a [singleton decorator](http://stackoverflow.com/a/9403992/355230) instead of inheritance. – martineau Jan 25 '14 at 22:31

1 Answers1

4

Use a dictionary to hold instances of each subclass instead

class Singleton(object):
    _instances = {}

    def __new__(cls, *args, **kwargs):
        if cls._instances.get(cls, None) is None:
            cls._instances[cls] = super(Singleton, cls).__new__(cls, *args, **kwargs)

        return Singleton._instances[cls]
Gulzar
  • 23,452
  • 27
  • 113
  • 201
fallenland
  • 525
  • 2
  • 6
  • I believe this is now a Multiton and not a Singleton? What if we don't want each subclass to have their own 'Singleton' but instead want them to share the same instantiated object? – hkh May 17 '23 at 16:30