Fundamentals 7 min read

Implementing a Python Singleton with Decorators

This article explains the singleton design pattern in Python, demonstrates how to implement it using a decorator with a wrapper class, provides step‑by‑step code examples, discusses its advantages, appropriate use cases, and cautions against overuse.

Python Programming Learning Circle
Python Programming Learning Circle
Python Programming Learning Circle
Implementing a Python Singleton with Decorators

In Python, the singleton pattern ensures a class has only one instance and provides a global point of access, which is useful for managing shared resources such as database connections or logging systems.

This article walks through implementing a singleton using a decorator, explaining the underlying concepts and showing the code step by step.

What is a Decorator?

A decorator in Python is a function that modifies or extends the behavior of another function or class without changing its source code.

Singleton Pattern Explanation

The singleton pattern guarantees that a class has only one instance; subsequent requests return the existing instance instead of creating a new one.

Code Breakdown

1. The wrapper class _SingletonWrapper stores the original class and holds the singleton instance.

class _SingletonWrapper:
    """A singleton wrapper class. Its instances would be created
    for each decorated class."""
    def __init__(self, cls):
        self.__wrapped__ = cls
        self._instance = None

2. The special method __call__ makes the wrapper callable and creates the instance on first use.

def __call__(self, *args, **kwargs):
    """Returns a single instance of decorated class"""
    if self._instance is None:
        self._instance = self.__wrapped__(*args, **kwargs)
    return self._instance

3. The decorator function singleton returns a wrapper object for the target class.

def singleton(cls):
    """A singleton decorator. Returns a wrapper object. A call on that object
    returns a single instance object of decorated class. Use the __wrapped__
    attribute to access the decorated class directly in unit tests."""
    return _SingletonWrapper(cls)

Using the Singleton Decorator

Example of applying the decorator to a Logger class and verifying that multiple instantiations refer to the same object.

@singleton
class Logger:
    def __init__(self):
        self.log = []

    def write_log(self, message):
        self.log.append(message)

    def read_log(self):
        return self.log

logger1 = Logger()
logger2 = Logger()
logger1.write_log("Log message 1")
print(logger2.read_log())  # Output: ['Log message 1']
print(logger1 is logger2)  # Output: True

Advantages of Using a Singleton

Global Access: Centralized control of a shared resource such as a database connection or logging service.

Efficiency: Reusing the same instance reduces memory usage and speeds up access, especially for resource‑intensive objects.

Ease of Testing: The underlying class can be accessed via the wrapper’s __wrapped__ attribute, allowing unit tests to bypass the singleton behavior.

When to Avoid Singletons

Overusing singletons can lead to tight coupling, make code harder to test and maintain, and introduce global state that may cause issues in multithreaded environments or when scaling the application.

Conclusion

If applied appropriately, the singleton pattern is a powerful tool. Using the decorator approach shown here lets you enforce singleton behavior while keeping the code clean and reusable; however, it is important to understand its trade‑offs and use it judiciously.

programmingdesign patternsingletondecorator
Python Programming Learning Circle
Written by

Python Programming Learning Circle

A global community of Chinese Python developers offering technical articles, columns, original video tutorials, and problem sets. Topics include web full‑stack development, web scraping, data analysis, natural language processing, image processing, machine learning, automated testing, DevOps automation, and big data.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.