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...

5
  • 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? Commented Jan 25, 2014 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. Commented Jan 25, 2014 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. Commented Jan 25, 2014 at 21:53
  • 1
    Take look at the answers to "Creating a singleton in python" or just "share global variables across modules" Commented Jan 25, 2014 at 22:02
  • If you want to create independent singleton classes, I suggest you use a singleton decorator instead of inheritance. Commented Jan 25, 2014 at 22:31

1 Answer 1

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]
Sign up to request clarification or add additional context in comments.

3 Comments

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 It would not make sense to create several subclasses in the first place if each of them is supposed to share the same instantiated object.
The problem with this solution is: assume we have a subclass class SubSingleton(Singleton) of Singleton with an __init__-method. Then multiple calls to SubSingleton() will indeed return the same instance, but the __init__-method will nevertheless be called on it each time. This misses the point of constructing the object only once, especially if __init__ does some heavy lifting.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.