美文网首页
python实现单例模式 2020-03-24(未经允许,禁止转

python实现单例模式 2020-03-24(未经允许,禁止转

作者: 9_SooHyun | 来源:发表于2020-03-28 23:35 被阅读0次

3种常见方式

  • 1.基于模块

python中模块是“单例”的,因为模块只在第一次被import时创建一个.pyc文件,.pyc文件创建完成后该模块的任意一次被import导入都直接加载.pyc文件从而导入模块内的同一个对象
例如,我们在模块A中定义一个类Test并实例化一个对象test

class Test:
    # 此处省略类体
test = Test()

然后我们在其他所有文件中from A import test都将得到同一个test对象
**把对象写在单独的module里然后被其他文件import就是单例

  • 2.基于装饰器——通过闭包保存的dict对象'_instance'来控制实例只有一个

这是很pythonic的方法。原始类并不关心自己单例与否,单例的实现只交给装饰器负责

def Singleton(cls):
    _instance = dict()
    def _singleton(*arg, **kw):
        if cls not in _instance:
            _instance[cls] = cls(*arg, **kw)
        return _instance[cls]
    return _singleton

@Singleton  # 等价于 Test = Singleton(Test)
class Test:
    # 此处省略函数体

说明:装饰器中return的是闭包_singleton,这个闭包保存了enclosing变量_instance这个字典,使得_instance这个字典一直保存在内存中,不会随着Test = Singleton(Test)完成而消失。这时,这个字典也是所谓“单例”的、唯一的,通过它来控制实例只有一个,因为在内存中只存在一个叫_instance的字典。那么,来一个类就判断一波,不在字典内就生成一个实例加入字典,然后返回这个字典中的实例,从而实现单例

局限性:被装饰的单例类不可被继承。因为一个类被装饰后,就从类变成了能够返回实例的函数,已经变成一个函数了,自然没有继承一说

  • 3.重写类的new()方法

在python类实例化对象的过程中,首先类执行new()方法创建对象,然后对象执行init()方法初始化自己本身,因此可以通过重写new()实现单例模式

# 通过将类的实例对象绑定到类变量_instance上实现单例
class Singleton(object):
    def __new__(cls, *args, **kw):
        if not hasattr(cls, '_instance'):
            # 【下面这句是重点!!!】
            cls._instance = super(Singleton, cls).__new__(cls, *args, **kw)
        return cls._instance

相关说明:

super不是函数,而是一个class

所以调用super,返回的是一个super对象

>>> type(super)
<class 'type'>
>>> type(int)
<class 'type'>

可以看到,super和int一样都是type类的实例,也就是都是class。那么调用super()自然返回super对象
super(Singleton, self).new(cls, args, *kw)实现对object类的new方法调用

局限性:重写new方法可以实现单例,每次实例化对象都将得到同一个,但是每实例化对象一次,init函数就会执行一次


补充:Java中,类可以声明为static的,这时它仅包含静态成员,不能使用 new 关键字创建静态类的实例。也就是静态类不能创建实例
单例模式的话,其实和实现静态类调用静态方法在效果上是一致的。但这样一来,代码就是基于对象而不是面向对象(大家都这么说,可能还得理解一下啊。。。)

单例模式的应用:单例往往对应一个资源管理者,如保证线程池有且只有一个,保证数据库连接池有且只有一个

相关文章

网友评论

      本文标题:python实现单例模式 2020-03-24(未经允许,禁止转

      本文链接:https://www.haomeiwen.com/subject/xkhzyhtx.html