Table Of Contents
- When One Instance is Enough
- Three Pythonic Approaches
- Choosing Your Weapon
- Singleton Gotchas
- Alternatives to Consider
- Deep Dive
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!