Definition of Singleton in Python
The Singleton is a design pattern that guarantees a class has only one single instance throughout your entire program. Every subsequent call to the constructor always returns the same instance, rather than creating a new one.
This pattern is part of the creational patterns described in the famous book Design Patterns: Elements of Reusable Object-Oriented Software by the Gang of Four. In Python, there are several elegant ways to implement it, which we will explore together in this article. If you want to deepen your knowledge of object-oriented programming, feel free to follow our comprehensive Python course.
The Singleton is one of the most well-known design patterns, but also one of the most debated. It is essential to understand when to use it — and when to avoid it.
Why Use a Singleton?
The Singleton addresses a specific need: controlling access to a unique shared resource. Here are the most common use cases:
- Database connection: you don't want to open multiple unnecessary connections.
- Configuration file: a single object centralizes reading your application's configuration.
- Logger: a unique entry point for writing log messages.
- Application cache: a shared dict that stores temporary data.
- Thread or connection pool: a unique manager that distributes resources.
The fundamental idea is that some objects only make sense if they exist as a single copy. Creating multiple instances of these objects could lead to inconsistencies, access conflicts, or resource waste.
Implementation with __new__
The most classic method for implementing a Singleton in Python is to override the __new__ method of your class. This special method is called before __init__ and controls the creation of the instance.
class Singleton:
_instance = None
def __new__(cls, *args, **kwargs):
if cls._instance is None:
cls._instance = super().__new__(cls)
return cls._instance
def __init__(self, value=None):
# Warning: __init__ is called on every call to Singleton()
if value is not None:
self.value = value
# Usage
a = Singleton("first")
b = Singleton("second")
print(a is b) # True
print(a.value) # second
print(id(a) == id(b)) # TrueLet's analyze what happens step by step:
- On the first call
Singleton("first"),_instanceisNone, so__new__creates a new instance. - Then,
__init__is called and assignsself.value = "first". - On the second call
Singleton("second"),_instancealready exists, so__new__returns the same instance. __init__is called again, overwritingself.valuewith"second".
Warning: with this implementation, __init__ is called on every instantiation. If you place initialization logic there, it will be executed multiple times. Use a flag to control this.
Protected version with initialization flag
To prevent __init__ from being executed multiple times, you can add a control attribute:
class Singleton:
_instance = None
_initialized = False
def __new__(cls, *args, **kwargs):
if cls._instance is None:
cls._instance = super().__new__(cls)
return cls._instance
def __init__(self, value=None):
if not self._initialized:
self.value = value
self._initialized = True
a = Singleton("first")
b = Singleton("second")
print(a.value) # first
print(b.value) # first (same instance, not reinitialized)This time, the value "first" is preserved because __init__ only executes once.
Implementation with a Decorator
A more Pythonic approach is to use a decorator. This decorator wraps any class and transforms it into a Singleton, without modifying its internal code:
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 Configuration:
def __init__(self, file="config.yml"):
self.file = file
self.parameters = self._load()
def _load(self):
# Simulated loading
return {"debug": True, "version": "1.0"}
# Usage
config1 = Configuration()
config2 = Configuration("other_config.yml")
print(config1 is config2) # True
print(config1.file) # config.yml
print(config2.parameters) # {'debug': True, 'version': '1.0'}This solution is elegant because it separates the Singleton logic from the business logic of the class. The decorator stores instances in a local dict, which even allows managing multiple independent Singleton classes.
Implementation with a Metaclass
For the most advanced cases, you can use a metaclass. A metaclass controls the creation of classes themselves, making it a powerful tool for the Singleton pattern:
class SingletonMeta(type):
_instances = {}
def __call__(cls, *args, **kwargs):
if cls not in cls._instances:
instance = super().__call__(*args, **kwargs)
cls._instances[cls] = instance
return cls._instances[cls]
class Logger(metaclass=SingletonMeta):
def __init__(self):
self.messages = []
def log(self, message):
self.messages.append(message)
print(f"[LOG] {message}")
# Usage
logger1 = Logger()
logger1.log("Application starting")
logger2 = Logger()
logger2.log("User connection")
print(logger1 is logger2) # True
print(len(logger1.messages)) # 2
print(logger1.messages) # ['Application starting', 'User connection']The SingletonMeta metaclass intercepts the __call__ call (triggered when you write Logger()) and checks if an instance already exists. This approach is the most robust and works perfectly with inheritance.
Implementation with a Python Module
There is an even simpler approach, specific to Python: using a module as a Singleton. In Python, modules are single-instance objects by nature. When you import a module, Python loads it only once and caches it.
# file: my_singleton.py
class _Configuration:
def __init__(self):
self.debug = True
self.version = "1.0"
self.base_url = "https://example.com"
# Unique instance at module level
config = _Configuration()
def get_parameter(key):
return getattr(config, key, None)# file: main.py
from my_singleton import config, get_parameter
print(config.debug) # True
print(get_parameter("version")) # 1.0
# Everywhere in your code, config is the same instance
config.debug = FalseThis approach is often recommended by the Python community because it is simple, readable, and idiomatic. No need for a complex class or metaclass.
Comparison of Different Approaches
| Method | Complexity | Inheritance | Thread-safe | Pythonic |
|---|---|---|---|---|
__new__ | Medium | ⚠️ Partial | ❌ No | ✅ Yes |
| Decorator | Low | ❌ No | ❌ No | ✅ Yes |
| Metaclass | High | ✅ Yes | ❌ No | ⚠️ Advanced |
| Module | Very low | N/A | ✅ Yes* | ✅✅ Very |
* Python's import mechanism is thread-safe by default thanks to the GIL.
Thread-safe Singleton
If your application is multi-threaded, classic Singleton implementations are not safe. Two threads could pass the if _instance is None check simultaneously. Here is a thread-safe version with a lock:
import threading
class SingletonThreadSafe:
_instance = None
_lock = threading.Lock()
def __new__(cls, *args, **kwargs):
if cls._instance is None:
with cls._lock:
# Double-checked locking
if cls._instance is None:
cls._instance = super().__new__(cls)
return cls._instance
def __init__(self):
pass
# Test with multiple threads
def create_instance():
instance = SingletonThreadSafe()
print(f"Thread {threading.current_thread().name}: {id(instance)}")
threads = [threading.Thread(target=create_instance) for _ in range(10)]
for t in threads:
t.start()
for t in threads:
t.join()Double-checked locking is an optimization technique: the first if avoids acquiring the lock unnecessarily if the instance already exists, while the second if (inside the with) ensures thread safety.
Practical Example: Database Manager
Let's look at a realistic example of using the Singleton to manage a database connection:
import sqlite3
import threading
class DatabaseManager(metaclass=SingletonMeta):
def __init__(self, db_path="app.db"):
self.db_path = db_path
self._connection = None
self._lock = threading.Lock()
@property
def connection(self):
if self._connection is None:
self._connection = sqlite3.connect(self.db_path)
return self._connection
def execute(self, query, params=None):
with self._lock:
cursor = self.connection.cursor()
if params:
cursor.execute(query, params)
else:
cursor.execute(query)
self.connection.commit()
return cursor
def fetch(self, query, params=None):
cursor = self.execute(query, params)
return cursor.fetchall()
def close(self):
if self._connection:
self._connection.close()
self._connection = None
# Usage throughout the application
db = DatabaseManager("my_application.db")
db.execute("CREATE TABLE IF NOT EXISTS users (id INTEGER PRIMARY KEY, name TEXT)")
db.execute("INSERT INTO users (name) VALUES (?)", ("Alice",))
# Elsewhere in the code, same instance
db2 = DatabaseManager()
results = db2.fetch("SELECT * FROM users")
print(results) # [(1, 'Alice')]Here, no matter where you instantiate DatabaseManager() in your code, you always get the same connection. This avoids opening multiple unnecessary connections and centralizes database management.
Best Practices and Caveats
When to Use the Singleton
- You need a unique global access point to a resource.
- Object creation is expensive (network connection, file reading).
- The object must maintain a consistent state shared across multiple parts of the code.
When to Avoid the Singleton
- Unit tests: the Singleton introduces global state that makes tests difficult to isolate. Prefer dependency injection.
- Tight coupling: classes that depend on a Singleton are coupled to its implementation.
- Single responsibility principle violation: the Singleton manages both its business logic and its lifecycle.
- No state needed: if your class has no state, simply use functions at the module level.
The Singleton is sometimes called an anti-pattern in the Python community. Before using it, ask yourself whether a simple module or dependency injection would be more appropriate.
Tips for a Good Implementation
- Prefer the module approach for simple cases — it's the most Pythonic way.
- Use the metaclass if you need inheritance or a strict object-oriented structure.
- Protect concurrent access with a lock (
threading.Lock) in a multi-threaded environment. - Document clearly that your class is a Singleton — add an explicit docstring.
- Provide a reset method to facilitate unit testing.
class Singleton:
"""Singleton class — only one instance is created.
Use Singleton.reset() in tests to reinitialize the instance.
"""
_instance = None
def __new__(cls, *args, **kwargs):
if cls._instance is None:
cls._instance = super().__new__(cls)
return cls._instance
@classmethod
def reset(cls):
"""Reset the instance (useful for testing)."""
cls._instance = NoneFrequently Asked Questions
What is the difference between a Singleton and a global variable?
A global variable is simply a value accessible everywhere, without any control over its creation or modification. The Singleton, on the other hand, encapsulates the creation logic and guarantees that only one instance exists. It provides strict control through the class itself, while a global variable can be overwritten at any time.
Does the Singleton work with inheritance in Python?
It depends on the implementation. With the __new__ method, inheritance can cause issues because the _instance attribute is shared. With a metaclass, each subclass will have its own entry in the _instances dictionary, which allows one Singleton per class in the inheritance hierarchy.
Is the Singleton thread-safe in Python?
No, classic implementations are not thread-safe. Even though the GIL (Global Interpreter Lock) offers some protection, it does not guarantee the atomicity of the check and creation. For a thread-safe Singleton, use a threading.Lock with the double-checked locking pattern, or opt for the module approach which is naturally thread-safe.
How can I learn to master design patterns in Python?
Design patterns like the Singleton become natural with practice and a solid understanding of object-oriented programming in Python. We recommend following our Python course on Believemy, which covers classes, metaclasses, and software design best practices in depth. You will learn to choose the right pattern for each concrete situation.