Python单例模式防止构造函数重复调用

python中一般我们会使用内置放方法__new__来实现单例

class Single(object):
    _instance = None

    def __new__(cls, *args, **kw):
        if cls._instance is None:
            cls._instance = object.__new__(cls, *args, **kw)
        return cls._instance

    def __init__(self):
        print('init')

以上代码有个缺陷,就是每次实例化后都会调用构造函数__init__, 我们想要的效果一般是第二次以后就直接返回之前的实例了,这才是单例嘛。

In [16]: for x in range(5):
    ...:     _ = Single()
    ...:
init
init
init
init
init

In [17]:

我们可以引入一个类属性来标志是否就行初始化,改造后代码如下

class Single(object):
    _instance = None
    _is_init = False

    def __new__(cls, *args, **kwargs):
        if cls._instance is None:
            cls._instance = object.__new__(cls, *args, **kwargs)
        return cls._instance

    def __init__(self):
        if Single._is_init:
            return
        print('init')
        Single._is_init = True

验证

In [18]: for x in range(5):
    ...:     _ = Single()
    ...:
init

In [19]:

我们也可以通过类装饰器来实现单例

class Singleton(object):
    def __init__(self, cls):
        self._cls = cls
        self._instance = {}

    def __call__(self):
        if self._cls not in self._instance:
            self._instance[self._cls] = self._cls()
        return self._instance[self._cls]

@Singleton
class Cls2(object):
    def __init__(self):
        print('init')

验证

In [20]: for x in range(5):
    ...:     _ = Cls2()
    ...:
init

In [21]: