Question
How to Implement a Singleton in Python: Patterns, Tradeoffs, and Pythonic Alternatives
Question
I have several classes that I might want to behave as singletons, for example a logger, although the exact use case is not the main point. I would prefer a solution that does not require repetitive boilerplate inside every class if inheritance or decoration can handle it.
I am comparing several possible approaches for implementing a singleton in Python and want to understand their tradeoffs.
Method 1: A decorator
def singleton(class_):
instances = {}
def getinstance(*args, **kwargs):
if class_ not in instances:
instances[class_] = class_(*args, **kwargs)
return instances[class_]
return getinstance
@singleton
class MyClass(BaseClass):
pass
Pros
- Decorators are additive and often feel more intuitive than multiple inheritance.
Cons
- Objects created through
MyClass()are singleton instances, butMyClassitself becomes a function rather than a class. - That means class methods and class-based introspection no longer behave normally.
For example:
x = MyClass()
y = MyClass()
t = type(x)
Here, x is y, but MyClass is no longer the original class object.
Method 2: A base class
class Singleton(object):
_instance = None
def __new__(cls, *args, **kwargs):
if not isinstance(cls._instance, cls):
cls._instance = object.__new__(cls)
return cls._instance
class MyClass(Singleton, BaseClass):
pass
Pros
MyClassremains a real class.
Cons
- Requires multiple inheritance.
__new__may become harder to reason about when combined with other base classes.
Method 3: A metaclass
class Singleton(type):
_instances = {}
def __call__(cls, *args, **kwargs):
if cls not in cls._instances:
cls._instances[cls] = super(Singleton, cls).__call__(*args, **kwargs)
return cls._instances[cls]
# Python 2
class MyClass(BaseClass):
__metaclass__ = Singleton
# Python 3
class MyClass(BaseClass, metaclass=Singleton):
pass
Pros
MyClassremains a real class.- The behavior naturally applies per class.
- Uses the metaclass mechanism directly.
Cons
- Are there any important downsides?
Method 4: A decorator that returns a subclass with the same name
def singleton(class_):
class class_w(class_):
_instance = None
def __new__(cls, *args, **kwargs):
if class_w._instance is None:
class_w._instance = super(class_w, cls).__new__(cls)
class_w._instance._sealed = False
return class_w._instance
def __init__(self, *args, **kwargs):
if self._sealed:
return
super(class_w, self).__init__(*args, **kwargs)
self._sealed = True
class_w.__name__ = class_.__name__
return class_w
@singleton
class MyClass(BaseClass):
pass
Pros
MyClassremains a real class.- Inheritance is handled automatically.
Cons
- It creates a wrapper subclass for every singleton class.
- The
_sealedattribute adds extra complexity. - It can interfere with
super()and customization of__new__or__init__.
Method 5: A module
Use a module file such as singleton.py and keep shared state there.
Pros
- Very simple.
Cons
- Not lazily instantiated in the same class-based way.
I am not looking for a debate about whether the singleton pattern is good or bad. Instead, I want to understand which implementation style is most Pythonic, especially in the sense of following the principle of least astonishment.
Short Answer
By the end of this page, you will understand what a singleton is in Python, how modules, __new__, decorators, and metaclasses can be used to implement it, and why Python developers often prefer simpler alternatives. You will also see the practical tradeoffs between a "true singleton class" and a module-level shared object.
Concept
A singleton is a pattern that ensures only one instance of something exists during a program's lifetime, while providing a global way to access it.
In Python, this idea appears often in things like:
- application configuration
- database connection managers
- logging helpers
- caches
- service registries
The important Python-specific detail is this:
- In many languages, singleton patterns are built into class design.
- In Python, modules are already singletons in practice because a module is imported once and then reused.
That is why many Python developers ask a different question:
Do you really need a singleton class, or do you just need one shared object?
Why this matters
Choosing the wrong implementation can make code harder to understand.
For example:
- A decorator that turns a class into a function can break class behavior.
- A metaclass can work, but may be harder for beginners to read.
- A module-level instance is simple and unsurprising.
In Python, the most Pythonic solution is usually the one that is:
- easiest to read
- easiest to test
- least magical
- least likely to surprise other developers
So the real lesson is not just how to build a singleton, but when a simpler shared-object design is better.
Mental Model
Think of a singleton like a single reception desk in an office.
- Many people can ask for the desk.
- But the office should not create a new reception desk each time.
- Everyone is directed to the same one.
In Python, a module is like the building directory that already points everyone to the same desk.
A singleton class is more like adding a guard who checks:
- "Has the desk already been created?"
- If yes, return the existing one.
- If not, create it once.
The simpler the guard system, the easier it is for everyone else in the office to understand what is happening.
Syntax and Examples
1. Simplest Pythonic approach: module-level instance
# logger_service.py
class Logger:
def log(self, message):
print(f"LOG: {message}")
logger = Logger()
Use it like this:
from logger_service import logger
logger.log("Application started")
Why this is often preferred
- The module is imported once.
loggeris created once.- Other files reuse the same object.
- It is easy to understand.
2. Singleton with __new__
class Logger:
_instance = None
def __new__(cls, *args, **kwargs):
if cls._instance is None:
cls._instance = super().__new__(cls)
return cls._instance
():
()
Step by Step Execution
Consider this example using __new__:
class Config:
_instance = None
_initialized = False
def __new__(cls):
if cls._instance is None:
print("Creating instance")
cls._instance = super().__new__(cls)
return cls._instance
def __init__(self):
if self._initialized:
print("Already initialized")
return
print("Running initialization")
self.settings = {"theme": "dark"}
self._initialized = True
x = Config()
y = Config()
print(x is y)
print(x.settings)
What happens step by step
x = Config()is executed.- Python calls
Config.__new__(Config).
Real World Use Cases
Shared configuration
A program may load configuration once and reuse it everywhere.
class AppConfig:
_instance = None
def __new__(cls):
if cls._instance is None:
cls._instance = super().__new__(cls)
cls._instance.debug = True
return cls._instance
Logging service
A single logger object can collect messages from different parts of the app.
Cache manager
A shared in-memory cache avoids creating separate caches in each module.
Database connection coordinator
Sometimes an app wants one connection manager object, even if the manager itself internally controls a pool.
Feature flag registry
A shared service can expose flags like is_beta_enabled across the application.
In practice, many of these are simpler as module-level objects rather than formal singleton classes.
Real Codebase Usage
In real projects, developers often use one of these patterns instead of a heavy singleton implementation:
Module-level shared object
# config.py
settings = {"debug": True}
This is the most common and readable option when one shared object is enough.
Lazy module-level factory
_instance = None
def get_logger():
global _instance
if _instance is None:
_instance = Logger()
return _instance
This gives lazy initialization without metaclasses.
Dependency injection
Instead of global access, the object is created once and passed where needed.
class UserService:
def __init__(self, logger):
self.logger = logger
This is common in testable codebases because it avoids hidden global state.
Guarded initialization
If using __new__, developers commonly add an initialization guard.
Common Mistakes
Mistake 1: Forgetting that __init__ can run more than once
Broken example:
class Logger:
_instance = None
def __new__(cls):
if cls._instance is None:
cls._instance = super().__new__(cls)
return cls._instance
def __init__(self):
self.logs = []
Problem:
- Every call to
Logger()resetsself.logs.
Fix:
class Logger:
_instance = None
_initialized = False
def __new__(cls):
if cls._instance is None:
cls._instance = super().__new__(cls)
return cls._instance
def ():
._initialized:
.logs = []
._initialized =
Comparisons
| Approach | Keeps real class? | Lazy creation? | Complexity | Common in Python? | Notes |
|---|---|---|---|---|---|
| Module-level instance | Yes | No, unless wrapped | Low | Very common | Simplest shared-object solution |
| Module-level factory | Yes | Yes | Low | Very common | Good balance of simplicity and laziness |
__new__ singleton | Yes | Yes | Medium | Sometimes | Must guard repeated __init__ |
| Metaclass singleton | Yes |
Cheat Sheet
Singleton quick reference in Python
Simplest shared object
# service.py
class Service:
pass
service = Service()
Lazy shared object
_instance = None
def get_service():
global _instance
if _instance is None:
_instance = Service()
return _instance
__new__ singleton
class Service:
_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):
if self._initialized:
._initialized =
FAQ
Why are modules often considered singletons in Python?
Because Python imports a module once and then reuses the same module object, so module-level state is naturally shared.
Is using a metaclass the best way to implement a singleton in Python?
Not always. It is powerful, but often more complex than necessary. A module-level object or factory is usually simpler.
What is the difference between __new__ and __init__ in a singleton?
__new__ controls object creation. __init__ configures the object after creation. In a singleton, __init__ may be called multiple times unless you guard it.
How do I check whether two singleton variables are the same object?
Use is:
a is b
Are singletons bad in Python?
Not automatically, but they can introduce hidden global state and make testing harder. Use them only when shared state is truly needed.
What is the most Pythonic singleton alternative?
Usually a module-level instance or a module-level getter function.
Can a decorator-based singleton break my class?
Yes. If the decorator returns a function wrapper, the original class identity and behavior may be lost.
Should I use a singleton for logging in Python?
Mini Project
Description
Build a small application-wide settings manager that behaves like a singleton. This project demonstrates how to ensure only one settings object exists while avoiding repeated initialization bugs.
Goal
Create a reusable Settings class where every call returns the same object and configuration is initialized only once.
Requirements
- Create a
Settingsclass using Python. - Ensure multiple
Settings()calls return the same object. - Prevent the configuration data from being reset on repeated construction.
- Add methods to set and get configuration values.
- Show that two variables reference the same instance.
Keep learning
Related questions
@staticmethod vs @classmethod in Python Explained
Learn the difference between @staticmethod and @classmethod in Python with clear examples, use cases, mistakes, and a mini project.
Call a Function by Name in a Python Module
Learn how to call a function by name in a Python module using strings, getattr, and safe patterns for dynamic function dispatch.
Catch Multiple Exceptions in One except Block in Python
Learn how to catch multiple exceptions in one Python except block using tuples, with examples, mistakes, and real-world usage.