SoFunction
Updated on 2025-05-14

5 ways to implement Python singleton mode

Singleton Pattern is a classic design pattern, and its core idea is to ensure that a class has only one instance during the entire program run and provides a global access point. This pattern is very useful in many scenarios, such as global configuration management, loggers, database connection pools, etc.

However, Python's flexibility makes it possible to implement singleton patterns in multiple ways, each with its characteristics and applicable scenarios. This article will introduce in detail the 5 common methods of implementing singleton patterns in Python, and analyze their advantages and disadvantages and applicable scenarios in depth to help you choose the most suitable solution.

Method 1: Global variables at the module level

Python's module itself is a natural singleton. The module will only be imported once, so a singleton can be implemented through global variables in the module.

Sample code

# 
class Singleton:
    def __init__(self):
         = "Singleton Instance"

# Define a global variablesingleton_instance = Singleton()

# Import instances directly when usingfrom singleton import singleton_instance
print(singleton_instance.value)  # Output: Singleton Instance

Principle analysis

When the module is first imported,singleton_instanceWill be initialized and stored in memory. Subsequent imports to this module will not re-execute the module code, but will directly return the loaded module object. therefore,singleton_instanceis a globally unique instance.

advantage

  • Simple and easy to use: No additional logic is required, and Python's module mechanism is directly utilized.
  • Natural support: The Python module itself is the best manifestation of singletons.

shortcoming

  • Not flexible enough: The instantiation process cannot be controlled dynamically, and is not suitable for scenarios where delayed initialization is required.
  • Limited functions: The instance can only be accessed through module import, which limits the scalability.

Applicable scenarios

Suitable for simple global object management, such as configuration files or static resources.

Method 2: Use a decorator

A decorator is a higher-order function that can enhance functionally to a class or function. With the decorator, we can easily implement singleton mode.

Sample 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 Singleton:
    def __init__(self, value):
         = value

# tests1 = Singleton("First")
s2 = Singleton("Second")
print()  # Output: Firstprint()  # Output: Firstprint(s1 is s2)  # Output: True

Principle analysis

DecoratorssingletonCalled during class definition, return a new functionget_instance. Each time an instance is created,get_instanceWill check whether an instance of this class already exists. If it does not exist, it is created and stored; otherwise, it returns the existing instance.

advantage

  • Easy to reuse: The same decorator can be applied to multiple classes.
  • Clear and intuitive: The logic of the decorator is independent of the class itself and is easy to maintain.

shortcoming

  • Depend on decorators: Decorators need to be used explicitly, which may increase code complexity.
  • Limited flexibility: The decorator implementation may not be applicable to complex initialization logic.

Applicable scenarios

Suitable for scenarios where singleton mode is required for multiple classes, especially lightweight applications.

Method 3: Use metaclass (__metaclass__)

Metaclasses are a high-level feature in Python that controls class creation behavior. With custom metaclasses, we can force the singleton pattern to be implemented when class creation is created.

Sample code

class SingletonMeta(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 Singleton(metaclass=SingletonMeta):
    def __init__(self, value):
         = value

# tests1 = Singleton("First")
s2 = Singleton("Second")
print()  # Output: Firstprint()  # Output: Firstprint(s1 is s2)  # Output: True

Principle analysis

MetaclassSingletonMetaRewrite__call__Method, check whether an instance of the class already exists when instantiating the class. If it does not exist, the parent class's__call__Method creates a new instance; otherwise, return the existing instance.

advantage

  • Highly flexible: You can fully control the class creation process.
  • Powerful: Applicable to complex singleton requirements, such as dynamically modifying the behavior of classes.

shortcoming

  • High learning cost: The concept of metaclasses is relatively abstract and may be difficult for beginners to understand.
  • Increased code complexity: The introduction of metaclasses may make the code difficult to maintain.

Applicable scenarios

Suitable for scenarios where deep customization of the class creation process is required, such as framework development.

Method 4: Rewrite __new__ Method

__new__is a method used in Python to create instances. By rewriting__new__,We can control the creation logic of the instance, thereby implementing the singleton pattern.

Sample code

class Singleton:
    _instance = None

    def __new__(cls, *args, **kwargs):
        if not cls._instance:
            cls._instance = super().__new__(cls, *args, **kwargs)
        return cls._instance

    def __init__(self, value):
         = value

# tests1 = Singleton("First")
s2 = Singleton("Second")
print()  # Output: Secondprint()  # Output: Secondprint(s1 is s2)  # Output: True

Principle analysis

__new__is the first step in class instantiation, responsible for allocating memory and returning instances. By__new__In the inspection_instanceWhether it already exists, we can ensure that the class has only one instance.

advantage

  • Simple implementation: Directly control the instantiation process, with clear logic.
  • Moderate flexibility: Suitable for most singleton needs.

shortcoming

  • Multiple calls__init__: Even if the instance already exists__init__It will still be called, which may lead to unexpected behavior.
  • Thread safety issues: In a multi-threaded environment, there may be race conditions.

Applicable scenarios

Suitable for simple singleton requirements, but attention should be paid to thread safety issues.

Method 5: Thread-safe singleton implementation

In a multithreaded environment, the above implementation may have problems. To ensure thread safety, singleton mode can be implemented in combination with thread locks.

Sample code

import threading

class Singleton:
    _instance = None
    _lock = ()

    def __new__(cls, *args, **kwargs):
        with cls._lock:
            if not cls._instance:
                cls._instance = super().__new__(cls, *args, **kwargs)
        return cls._instance

    def __init__(self, value):
         = value

# tests1 = Singleton("First")
s2 = Singleton("Second")
print()  # Output: Secondprint()  # Output: Secondprint(s1 is s2)  # Output: True

Principle analysis

passEnsure that in a multi-threaded environment,__new__The instantiation logic in the method is thread-safe. Only when_instanceA new instance will only be created when it does not exist.

advantage

  • Thread safety: Avoid competition conditions in multi-threaded environments.
  • High reliability: Suitable for concurrent scenarios.

shortcoming

  • Performance overhead: Increases the overhead of locks, which may affect performance.
  • Implementation complex: Compared with other methods, the code is slightly more complicated.

Applicable scenarios

Suitable for singleton requirements in multithreaded environments, such as global object management in web applications.

Summarize

method advantage shortcoming
Module-level variables Simple, natural support Not flexible enough
Decorators Easy to reuse, clear Need to use decorator explicitly
Metaclass Flexible and powerful Metaclass concept complex
__new__ Method Simple implementation Multiple calls __init__ may have problems
Thread-safe implementation Suitable for multi-threaded environments Increase lock overhead

Each method has its applicable scenarios, and you need to weigh the trade-offs when choosing according to specific needs. If you are pursuing simplicity and efficiency, it is recommended to use module-level global variables or__new__Method; If higher flexibility or thread safety is required, you can choose a metaclass or thread safety implementation.

This is the end of this article about the 5 ways to implement Python singleton mode. For more related content on Python singleton mode, please search for my previous articles or continue browsing the related articles below. I hope everyone will support me in the future!