博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
python单例模式
阅读量:6219 次
发布时间:2019-06-21

本文共 2976 字,大约阅读时间需要 9 分钟。

单例模式是一种常用的软件设计模式.

在单例模式的核心结构中,只包含一个被称为单例类的特殊类.

通过单例模式可以保证系统中一个类只有一个实例,而且这个实例可以轻易被外界访问,方便控制实例对象的个数以节约系统资源.

单例模式是解决一个系统中某个类的实例化对象有且只能有一个的最好解决方案.

单例模式的要点有三个:

  • 某个类只能有一个实例
  • 这个类必须自行创建其唯一实例
  • 这个类必须自行向整个系统提供这个唯一实例.

在python中,单例模式有三种实现方式:

方法一,使用__new__方法

先定义一个类,类中定义__new__方法,然后将类的一个实例类绑定到类变量中.

如果类的_instance值为None,则说明这个类还没有被实例化过,程序会自动实例化一个类的实例,然后返回.

如果类的_instance值不为None,则程序会直接返回_instance.

代码如下:

class Singleton(object):    _instance = None        def __init__(self):        pass        def __new__(cls, *args, **kwargs):            if not cls._instance:            cls._instance = super(Singleton, cls).__new__(cls, *args, **kwargs)          return cls._instance   class MyClass(Singleton):      a = 1

在上面的代码中,我们将类的实例和一个类变量 _instance关联起来.

如果 cls._instance为 None 则创建实例,否则直接返回cls._instance

用上来定义的类实例化两个对象:

cls1=MyClass()cls2=MyClass()print(id(cls1))print(id(cls2))print(cls1 == cls2)print(cls1 is cls2)

得到的结果

4360648043606480TrueTrue

方法二,使用decorator装饰器

我们知道,装饰器(decorator)可以动态地修改一个类或函数的功能。

在这里使用装饰器来装饰某个类,使其只能生成一个实例,代码如下:

def singleton(cls):    instances={}    def getinstance(*args,**kwargs):        if cls not in instances:            instances[cls]=cls(*args,**kwargs)        return instances[cls]    return getinstance@singletonclass MyClass(object):    a=1

在上面,我们定义了一个装饰器singleton,它返回了一个内部函数getinstance,该函数会判断某个类是否在字典instances中,

如果不存在,则会将cls作为key,cls(*args, **kw)作为value存到instances中,否则,直接返回instances[cls]

使用上面定义的类实例化两个对象,比较两个对象

cls1=MyClass()cls2=MyClass()print(id(cls1))print(id(cls2))print(cls1 == cls2)print(cls1 is cls2)

得到的结果为:

4367201643672016TrueTrue

方法三,使用元类(metaclass)

元类(metaclass)可以控制类的创建过程,它主要做三件事:

拦截类的创建修改类的定义返回修改后的类

用元类实现单例模式的代码如下:

class Singleton(type):        _inst = {}            def __call__(self, *args, **kw):            if self not in self._inst:                self._inst[self] = super(Singleton, self).__call__(*args, **kw)            return self._inst[self]        class MyClass(metaclass=Singleton):        def __init__(self):            self.xx = 0    cls1=MyClass()    cls2=MyClass()    print(id(cls1))    print(id(cls2))    print(cls1 == cls2)    print(cls1 is cls2)

得到的结果为:

4347798443477984TrueTrue

方法四,使用classmethod方法创建单例模式

class Foo:    _instance = None    def __init__(self):        pass    @classmethod    def get_instance(cls):        if cls._instance:            return cls._instance        else:            obj=cls()            cls._instance=obj            return objcls1=Foo.get_instance()     # 实例化对象a1时,没有执行Foo这个类的__init__方法,直接执行Foo类的get_instance方法,在这里cls代指的是Foo类                            # 前面把_instance赋值为None,所以直接执行else中的语句,实例化一个obj对象,然后把obj对象中的_instance方法赋值为obj对象本身,然后返回obj对象cls2=Foo.get_instance()     # 实例化a1时,Foo类中的_instance已经被赋值为obj对象,所以再次执行Foo中的get_instance方法时,是执行if中的语句                            # 此时cls._instance就指的是obj对象,所以这里也返回obj这个对象print(id(cls1))print(id(cls2))print(cls1 == cls2)print(cls1 is cls2)

这种方法由于在实例化对象时要调用类中的get_instance方法,所以用的不多,知道即可.

特别声明

Python的模块是天然的单例模式

在一个py文件中,多次导入同一个模块,这个模块也只有在第一次的时候被导入,后续的该模块导入语句都不会再执行了

转载地址:http://oslja.baihongyu.com/

你可能感兴趣的文章
C++数值类型极限值的获取
查看>>
Bag标签之中的一个行代码实行中文分词实例3
查看>>
3295 落单的数 九章算法面试题
查看>>
synchronized同步块和volatile同步变量
查看>>
spark入门
查看>>
计算某个特定分隔符分隔的字符串的和
查看>>
解决IE11 Array没有find的方法
查看>>
webpack 引入jquery和第三方jquery插件
查看>>
损失函数的概率验证及性质
查看>>
C#-----------------------------回收机制中Destroy与null的作用
查看>>
mysql读写分离总结
查看>>
ubuntu默认防火墙
查看>>
使用 GeoIP2 获取 IP 的地理位置
查看>>
详解spl_autoload_register()函数
查看>>
微软Azure AspNetCore微服务实战第2期
查看>>
Deepin-安装QQ音乐(Windows程序)
查看>>
Spring Boot 2.0(七):Spring Boot 如何解决项目启动时初始化资源
查看>>
移动手机号神州行去香港购买境外流量包方法和注意事项
查看>>
OpenResty(nginx+lua) 入门
查看>>
斗地主AI算法——第二章の数据结构
查看>>