Rethinking Creational Patterns: Why Singletons Fail in Python

ArjanCodes////3 min read

Beyond the Hype of Creational Patterns

Design patterns fall into three buckets: behavioral, structural, and creational. While behavioral patterns like manage communication and structural patterns handle assembly, creational patterns dictate how we instantiate objects. The is perhaps the most famous creational pattern, but in the world of modern development, it has become a notorious anti-pattern. Understanding why it fails helps us appreciate better alternatives like the .

Prerequisites

To get the most out of this tutorial, you should be comfortable with classes and inheritance in . Familiarity with , decorators, and the concept of (the with statement) will help you grasp the more advanced implementation details.

The Problem with Singletons

A restricts a class to a single instance. While this sounds useful for loggers or database managers, it creates a global state that makes testing nearly impossible. Because you cannot easily reset the instance between test runs, your tests become coupled. Furthermore, lacks private constructors. Implementing a true singleton requires "trickery" like metaclasses:

class Singleton(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 Logger(metaclass=Singleton):
    def log(self, msg):
        print(f"Log: {msg}")
Rethinking Creational Patterns: Why Singletons Fail in Python
QUESTIONABLE Object Creation Patterns in Python 馃

In this snippet, we override the __call__ method of a metaclass to intercept instantiation. If the instance exists in our dictionary, we return it; otherwise, we create it. It works, but it鈥檚 overkill. modules are already singletons by nature鈥攊mporting a module multiple times always returns the same object. Just use a module.

Implementing an Object Pool

The is a smarter generalization. Instead of one instance, it manages a cache of reusable objects. This is vital when object creation is expensive, such as maintaining .

class ReusablePool:
    def __init__(self, size):
        self.free = [Reusable() for _ in range(size)]
        self.in_use = []

    def acquire(self):
        if not self.free:
            raise Exception("No objects available")
        obj = self.free.pop(0)
        self.in_use.append(obj)
        return obj

    def release(self, obj):
        self.in_use.remove(obj)
        self.free.append(obj)

Safety with Context Managers

Manually calling acquire and release is error-prone. If your code crashes before releasing, you leak resources. We solve this by wrapping the pool in a :

class PoolManager:
    def __init__(self, pool):
        self.pool = pool

    def __enter__(self):
        self.obj = self.pool.acquire()
        return self.obj

    def __exit__(self, type, value, traceback):
        self.pool.release(self.obj)

Now, the syntax with PoolManager(my_pool) as obj: ensures the object returns to the pool even if an exception occurs. Always remember: when an object returns to the pool, you must reset its state to prevent data leaks between different parts of your application.

Topic DensityMention share of the most discussed topics 路 13 mentions across 7 distinct topics
31%products
15%products
15%products
15%products
8%products
Other topics
15%
End of Article
Source video
Rethinking Creational Patterns: Why Singletons Fail in Python

QUESTIONABLE Object Creation Patterns in Python 馃

Watch

ArjanCodes // 15:10

On this channel, I post videos about programming and software design to help you take your coding skills to the next level. I'm an entrepreneur and a university lecturer in computer science, with more than 20 years of experience in software development and design. If you're a software developer and you want to improve your development skills, and learn more about programming in general, make sure to subscribe for helpful videos. I post a video here every Friday. If you have any suggestion for a topic you'd like me to cover, just leave a comment on any of my videos and I'll take it under consideration. Thanks for watching!

What they talk about
AI and Agentic Coding News
Who and what they mention most
Python
33.3%5
Python
20.0%3
Python
20.0%3
Pydantic
13.3%2
3 min read0%
3 min read