Navigation

Python

How to Create Singleton Classes in Python

Build bulletproof Singleton patterns in Python - because sometimes you really do need just one instance to rule them all.

Table Of Contents

When One Instance is Enough

Database connections, configuration managers, logging systems - some resources should have exactly one instance across your entire application. But Python doesn't have private constructors. So how do we enforce the Singleton pattern?

Three Pythonic Approaches

# Method 1: Using __new__
class Singleton:
    _instance = None
    
    def __new__(cls):
        if cls._instance is None:
            cls._instance = super().__new__(cls)
        return cls._instance
    
    def __init__(self):
        if not hasattr(self, 'initialized'):
            self.initialized = True
            self.value = 0

# Method 2: Decorator approach
def singleton(cls):
    instances = {}
    def get_instance(*args, **kwargs):
        if cls not in instances:
            instances[cls] = cls(*args, **kwargs)
        return instances[cls]
    return get_instance

@singleton
class Database:
    def __init__(self):
        self.connection = "Connected to database"

# Method 3: Metaclass approach
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 ConfigManager(metaclass=SingletonMeta):
    def __init__(self):
        self.settings = {"debug": True}

# Usage
s1 = Singleton()
s2 = Singleton()
print(s1 is s2)  # True

db1 = Database()
db2 = Database()
print(db1 is db2)  # True

Choosing Your Weapon

Each approach has its sweet spot:

  • __new__ method: Simple and straightforward, but requires careful __init__ handling
  • Decorator pattern: Clean and reusable, perfect for retrofitting existing classes
  • Metaclass approach: Most powerful, supports inheritance, but adds complexity

Singleton Gotchas

  • Thread safety: None of these are thread-safe by default
  • Testing: Singletons can make unit testing harder (consider dependency injection)
  • Global state: Singletons are essentially global variables in disguise

Alternatives to Consider

Before reaching for Singleton, consider:

  • Dependency injection
  • Module-level instances (Python modules are singletons!)
  • Factory patterns with instance caching

Deep Dive

Master advanced patterns with Python metaclasses, explore Python's design patterns, or learn about Python's import system for module-level singletons.

Share this article

Add Comment

No comments yet. Be the first to comment!

More from Python