When designing an application, certain situations demand that a class should have only one instance. The Singleton design pattern addresses this need by ensuring that a class has only one instance and provides a global point of access to that instance. In this article, we will delve into how to implement the Singleton pattern in Python with detailed examples.
1. Understanding the Singleton Design Pattern.
- The Singleton pattern restricts the instantiation of a class to a single object.
- This is particularly useful when we want to control access to some shared resource, such as a database connection or a file.
- Implementing the Singleton pattern involves creating a class that allows only one instance to be created and providing a way to access that instance.
2. Implementing the Singleton Pattern in Python.
- Here, we present a few methods to implement the Singleton pattern in Python:
2.1 Method 1: Use a Class Variable to Save the Instance.
- One of the simplest ways to implement a Singleton in Python is by using a class variable to save a single instance.
- You should also implement a class method ( decorated by the @classmethod ), in this method, it will process and return the singleton object of the class.
- Below is the example source code.
# singleton_module.py class Singleton: instance_obj = None def __init__(self): # initialization code print('instance is created.') @classmethod def get_singleton(cls): if cls.instance_obj == None: cls.instance_obj = Singleton() return cls.instance_obj def test_singleton_method1(): singleton_instance = Singleton.get_singleton() singleton_instance1 = Singleton.get_singleton() print(id(singleton_instance)) print(id(singleton_instance1)) if __name__ == "__main__": test_singleton_method1()
- When you run the above example Python source code, you will get the below output.
instance is created. 4450889872 4450889872
- From the above example code execution output, we can see the class Singleton‘s __init__ method is called only once when you call the get_singleton() method for the first time.
- The 2 Python object’s id is the same, which means they refer to the same object ( singleton instance of the class ).
2.2 Method 2: Using a Decorator.
- We can also use a decorator to ensure that only one instance of a class is created.
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 SingletonClass: def __init__(self): print('SingletonClass __init__ is called.') pass def test_singleton_method2(): obj1 = SingletonClass() obj2 = SingletonClass() print(id(obj1)) print(id(obj2)) if __name__ == "__main__": test_singleton_method2()
- When you run the above example source code, it will generate the below output.
SingletonClass __init__ is called. 4530496400 4530496400
2.3 Method 3: Using a Metaclass.
- Using a metaclass allows us to control the instantiation of the class and enforce the Singleton pattern.
class SingletonMeta(type): _instances = {} def __call__(cls, *args, **kwargs): if cls not in cls._instances: cls._instances[cls] = super(SingletonMeta, cls).__call__(*args, **kwargs) return cls._instances[cls] class SingletonClass1(metaclass=SingletonMeta): def __init__(self): # initialization code print('SingletonClass1 __init__ is called.') pass def test_singleton_method3(): obj1 = SingletonClass1() obj2 = SingletonClass1() print(id(obj1)) print(id(obj2)) if __name__ == "__main__": test_singleton_method3()
- When you run the above example source code, it will generate the below output.
SingletonClass1 __init__ is called. 4424829392 4424829392
3. Conclusion.
- Implementing the Singleton pattern in Python ensures that only one instance of a class exists throughout the application’s lifecycle.
- We explored various methods, including using a class method and variable, decorators, and metaclasses, to achieve this.
- Understanding when and how to apply the Singleton pattern is crucial for ensuring the efficient management of shared resources and maintaining control over class instantiation.