DEV Community

Aman Kumar
Aman Kumar

Posted on

Singleten Design Patten in Python

The Singleton pattern is a creational design pattern that restricts the instantiation of a class to a single object. In Python, this is commonly used for shared resources like database connections, loggers, or configuration settings.

Singleton ensures:

  • Only one object instance exists
  • Global shared access point is available

Basic Singleton Example

class Singleton:

    _instance = None

    def __new__(cls):

        if cls._instance is None:
            cls._instance = super().__new__(cls)

        return cls._instance

obj1 = Singleton()
obj2 = Singleton()

print(obj1 is obj2)
Enter fullscreen mode Exit fullscreen mode

⚠️ Problem in Multithreading

Two threads may create multiple instances simultaneously.

Thread-Unsafe Singleton

class Singleton:

    _instance = None

    def __new__(cls):

        if cls._instance is None:
            cls._instance = super().__new__(cls)

        return cls._instance
Enter fullscreen mode Exit fullscreen mode

✅ Thread-Safe Singleton Using Lock

import threading

class Singleton:

    _instance = None
    _lock = threading.Lock()

    def __new__(cls):

        with cls._lock:

            if cls._instance is None:
                cls._instance = super().__new__(cls)

        return cls._instance
Enter fullscreen mode Exit fullscreen mode

Singleton Using Decorator

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 Database:
    pass

db1 = Database()
db2 = Database()

print(db1 is db2)
Enter fullscreen mode Exit fullscreen mode

Singleton Using Metaclass

class SingletonMeta(type):

    _instances = {}

    def __call__(cls, *args, **kwargs):

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

        return cls._instances[cls]

class Logger(metaclass=SingletonMeta):
    pass

obj1 = Logger()
obj2 = Logger()

print(obj1 is obj2)
Enter fullscreen mode Exit fullscreen mode

📊 Best Singleton Approach

Top comments (0)