Implementing Singleton Pattern in Python: Multiple Approaches
Core Concept
The singleton pattern ensures that a class maintains only one instance throughout the application lifecycle while providing global access to that instance.
Implementation Methods
Method 1: Custom __new__ Method
class UniqueInstance:
_existing_instance = None
def __new__(cls):
if cls._existing_instance is None:
cls._existing_instance = super().__new__(cls)
return cls._existing_instance
# Usage example
first_object = UniqueInstance()
second_object = UniqueInstance()
print(first_object is second_object) # True
This approach overrides the __new__ method to control instance creation. The class variable _existing_instance tracks weather an instance already exists.
Method 2: Callable Class Implementation
class CallableSingleton:
_single_object = None
def __new__(cls):
if cls._single_object is None:
cls._single_object = super().__new__(cls)
return cls._single_object
def __call__(self):
return self._single_object
# Usage example
obj1 = CallableSingleton()
obj2 = CallableSingleton()
print(obj1 is obj2) # True
By implementing the __call__ method, instances of this class can be invoked like functions while maintaining singleton behavior.
Method 3: Decorator-Based Approach
def enforce_singleton(target_class):
created_instances = {}
def retrieve_instance(*constructor_args, **constructor_kwargs):
if target_class not in created_instances:
created_instances[target_class] = target_class(*constructor_args, **constructor_kwargs)
return created_instances[target_class]
return retrieve_instance
@enforce_singleton
class DecoratedSingleton:
def __init__(self):
pass
instance_one = DecoratedSingleton()
instance_two = DecoratedSingleton()
print(instance_one is instance_two) # True
The decorator maintains a dictionary of created instances and ensures only one instance per class is created.
Method 4: Module-Level Singleton
# unique_module.py
class ModuleSingleton:
def __init__(self):
self.identifier = "unique"
# Create single instance at module level
application_singleton = ModuleSingleton()
# main_application.py
from unique_module import application_singleton
reference_one = application_singleton
reference_two = application_singleton
print(reference_one is reference_two) # True
Python modules are inherently singletons since import statements execute module code only once. This approach leverages that behavior for singleton implementation.