How to define a Python singleton?

Is there a simple, elegant way to define a Python singleton?

Sure! One straightforward way to define a Python singleton is by using a class variable to store the instance. This ensures that only one instance of the class is created.

class Singleton:
    _instance = None

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

singleton1 = Singleton()
singleton2 = Singleton()
print(singleton1 is singleton2)  # Outputs: True

In this approach, the __new__ method ensures that only one instance of the class is ever created. It’s quick, effective, and uses Python’s object-oriented principles.

That’s a solid starting point! If you’re looking for a more elegant and reusable approach, you can implement a Python singleton using a decorator. This method allows you to encapsulate the singleton logic into a reusable wrapper:

def singleton(cls):
    instances = {}
    def wrapper(*args, **kwargs):
        if cls not in instances:
            instances[cls] = cls(*args, **kwargs)
        return instances[cls]
    return wrapper

@singleton
class Singleton:
    pass

singleton1 = Singleton()
singleton2 = Singleton()
print(singleton1 is singleton2)  # Outputs: True

With this approach, you don’t have to modify the class itself. The decorator pattern makes it easier to apply the python singleton pattern to multiple classes, keeping your code DRY and clean.

Great points above! If you need even more control and flexibility, you can implement a Python singleton using a metaclass. This is a more advanced approach that gives you complete control over how the class and its instances are created.

class SingletonMeta(type):
    _instances = {}

    def __call__(cls, *args, **kwargs):
        if cls not in cls._instances:
            cls._instances[cls] = super(SingletonMeta, cls).__call__(*args, **kwargs)
        return cls._instances[cls]

class Singleton(metaclass=SingletonMeta):
    pass

singleton1 = Singleton()
singleton2 = Singleton()
print(singleton1 is singleton2)  # Outputs: True

Using a metaclass ensures that the singleton logic is baked into the class creation process itself. While this approach may be overkill for simpler use cases, it’s perfect when you need the python singleton pattern in a more complex application.