Four ways to achieve Singleton

Realization (recommended) method based __new__

When we instantiate an object, is the first implementation of __new__ method ** class ** (we did not write the default call object .__ new__), instantiate an object ; and then re-execute ** __init__ method class **, this object is initialized, all based on this we can achieve a singleton

# 重写__new__方法,实现每一次实例化的时候,返回同一个instance对象
class Singleton:
    def __new__(cls, *args, **kwargs):      
        #判断类cls是否有_instance属性
        if not hasattr(cls, '_instance'):  #  _instance不能改成其他变量,改了单例模式就失效了
            #将一个类的实例绑定到类属性_instance上
            cls._instance = object.__new__(Singleton)
        return cls._instance  # 下一个实例化对象返回的是上一个的对象

    def __init__(self, name, age):
        # 第二个实例对象s2虽然返回的是第一个对象,但是还是会走init方法,把name和age修改了
        self.name = name
        self.age = age

s1 = Singleton('张三', 24)
s2 = Singleton('李四', 20)
print(s1, s2)  # 这两实例都一样
print(s1.name, s2.name)
print(id(s1))
print(id(s2))

Note : ** __ new__ method can not be avoided trigger __init__ method, the initial members of the variable will be overwritten. **

Singleton module

Python module is a natural single-mode embodiment, as introduced in the first module, generates a .pycfile, when introducing the second time, will be directly loaded .pycfile, rather than performing block code again.

#foo1.py
class Singleton(object):
    def foo(self):
        pass
singleton = Singleton()


#foo.py
from foo1 import singleton

Decorator

Principle: decorator used to control the class calls __call__ method.

def singleton(cls, *args, **kw):
    instance = {}
    def _singleton(args):
        if cls not in instance:
            instance[cls] = cls(*args, **kw)
        return instance[cls]
    return _singleton

@singleton
class A:
    pass

Yuan class method

'''
此方法是在__new__方法的更上层对实例化过程进行控制。

原理:执行元类的__new__方法和__init__方法用来实例化类对象,__call__ 方法用来对实例化的对象的实例即类的对象进行控制。__call__方法会调用实例类的 __new__方法,用于创建对象。返回对象给__call__方法,然后调用类对象的 __init__方法,用于对对象初始化。
'''
class Singleton1(type):
    def __init__(self, *args, **kwargs):
        self.__instance = None
        super(Singleton1,self).__init__(*args, **kwargs)

    def __call__(self, *args, **kwargs):
        if self.__instance is None:
            self.__instance = super(Singleton1,self).__call__(*args, **kwargs)
        return self.__instance

class Singleton2(type):
    _inst = {}
    def __call__(cls, *args, **kwargs):
        print(cls)
        if cls not in cls._inst:
            cls._inst[cls] = super(Singleton2, cls).__call__(*args)
        return cls._inst[cls]

class C(metaclass=Singleton1):
    pass

In addition to a single module exceptions, the nature of several other modes is provided by an intermediate variable, to determine whether the class has been instantiated. Difference is the position of the intermediate variable, or set the metaclass, or encapsulated in a function, a class, or provided as a static variable.

Note: Access to the intermediate variables and changing presence thread safety problems: the need to open the lock processing when multi-threaded mode.

Guess you like

Origin www.cnblogs.com/gaohuayan/p/11482209.html