Fundamentals 10 min read

Implementing the Singleton Pattern in Python: Multiple Approaches and Thread Safety

This article explains the Singleton design pattern in Python, covering various implementation methods—including modules, decorators, classic classes, __new__ method, and metaclasses—while demonstrating thread‑safety concerns and solutions with locking, and provides complete code examples for each approach.

Python Programming Learning Circle
Python Programming Learning Circle
Python Programming Learning Circle
Implementing the Singleton Pattern in Python: Multiple Approaches and Thread Safety

The Singleton pattern ensures that a class has only one instance, which is useful for shared resources such as configuration objects.

Python offers several ways to implement a singleton:

Using a module (modules are naturally singletons because they are loaded only once).

Using a decorator that caches the created instance.

Using a class with a classmethod that creates and stores a single instance.

Using the __new__ method together with a lock to guarantee thread safety.

Using a metaclass that overrides __call__ to enforce a single instance.

Below are the key code examples for each approach.

Module approach

<code>class Singleton(object):
    def foo(self):
        pass
singleton = Singleton()
</code>

Import the singleton elsewhere with:

<code>from mysingleton import singleton
</code>

Decorator approach

<code>def Singleton(cls):
    _instance = {}
    def _singleton(*args, **kargs):
        if cls not in _instance:
            _instance[cls] = cls(*args, **kargs)
        return _instance[cls]
    return _singleton

@Singleton
class A(object):
    a = 1
    def __init__(self, x=0):
        self.x = x

a1 = A(2)
a2 = A(3)
</code>

Classmethod approach

<code>class Singleton(object):
    @classmethod
    def instance(cls, *args, **kwargs):
        if not hasattr(Singleton, "_instance"):
            Singleton._instance = Singleton(*args, **kwargs)
        return Singleton._instance

# usage
obj = Singleton.instance()
</code>

When used in multithreaded environments, the simple classmethod version can create multiple instances. Adding a lock solves the problem:

<code>import threading, time

class Singleton(object):
    _instance_lock = threading.Lock()
    def __init__(self):
        time.sleep(1)
    @classmethod
    def instance(cls, *args, **kwargs):
        with cls._instance_lock:
            if not hasattr(cls, "_instance"):
                cls._instance = cls(*args, **kwargs)
        return cls._instance
</code>

Running multiple threads that call Singleton.instance() now prints the same object address, confirming thread‑safe singleton behavior.

__new__ method approach

<code>class Singleton(object):
    _instance_lock = threading.Lock()
    def __new__(cls, *args, **kwargs):
        if not hasattr(cls, "_instance"):
            with cls._instance_lock:
                if not hasattr(cls, "_instance"):
                    cls._instance = object.__new__(cls)
        return cls._instance

obj1 = Singleton()
obj2 = Singleton()
print(obj1, obj2)  # same address
</code>

Metaclass approach

<code>class SingletonType(type):
    _instance_lock = threading.Lock()
    def __call__(cls, *args, **kwargs):
        if not hasattr(cls, "_instance"):
            with cls._instance_lock:
                if not hasattr(cls, "_instance"):
                    cls._instance = super(SingletonType, cls).__call__(*args, **kwargs)
        return cls._instance

class Foo(metaclass=SingletonType):
    def __init__(self, name):
        self.name = name

obj1 = Foo('name')
obj2 = Foo('name')
print(obj1, obj2)  # same address
</code>

All the above methods achieve the same goal: only one instance of the class exists throughout the program, with the metaclass and __new__ approaches offering the most transparent usage (i.e., obj = Foo() works as usual).

In addition to the technical explanations, the article also includes promotional sections encouraging readers to follow the public account and scan QR codes for free Python learning resources.

PythonThread Safetydesign patternsingletonModuledecoratormetaclass
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.