zoukankan      html  css  js  c++  java
  • python单例模式原理及实现

    python单例模式的原理及实现

    什么是单例模式:
    单例模式即一个类有且仅有一个实例。

    为什么要用:
    全局变量,因为这比函数的参数传来传去更容易让人理解。确实在很多场景下用全局变量很方便。不过如果代码规模增大,并且有多个文件的时候,全局变量就会变得比较混乱。
    你可能不知道在哪个文件中定义了相同类型甚至重名的全局变量,也不知道这个变量在程序的某个地方被做了怎样的操作。
    单例模式保证了在程序的不同位置都可以且仅可以取到同一个对象实例:如果实例不存在,会创建一个实例;如果已存在就会返回这个实例。因为单例是一个类,所以你也可以为其提供相应的操作方法,以便于对这个实例进行管理。

    python中,一个类创建对象实例是通过调用父类object的 __new__(cls)方法来创建对象的,因此我们可以通过重写 __new__(cls)方法去实现类只创建一个实例

    class Sun(object):
        __instance=None #定义一个类属性做判断
        def __new__(cls):
            if cls.__instance==None:
                #如果__instance为空证明是第一次创建实例
                #通过父类的__new__(cls)创建实例
                cls.__instance==object.__new__(cls)
                return cls.__instance
            else:
                #返回上一个对象的引用
                return cls.__instance
    a = Sun()
    print(id(a))
    b = Sun()
    print(id(b))

     

    注意:

     

    1)__new__方法是静态类方法,虽然没有加静态类方法的装饰器;

     

    2)A继承object类,虽然通常可以省略object字样。但这里省略就无法执行__new__方法。若A继承其他类,同样可以使用object的__new__方法,也可以使用父类的__new__方法;

     

    3)在实例化对象的时候,__new__方法在__init__方法之前执行;

     

    4)__new__必须返回一个对象,才能给__init__初始化。

     

    __init__初始化会影响属性的内容。在使用单例模式时,尽量避免初始化属性或者初始化属性之前先判断是否存在该属性。

    使用函数装饰器实现单例

    使用类装饰器实现单例

    def singleton(cls):
        _instance = {}#使用不可变的类地址作为键,其实例作为值,每次创造实例时,
    #首先查看该类是否存在实例,存在的话直接返回该实例即可,
    #否则新建一个实例并存放在字典中。
    def inner(): if cls not in _instance: _instance[cls] = cls() return _instance[cls] return inner @singleton class Cls(object): def __init__(self): pass cls1 = Cls() cls2 = Cls() print(id(cls1) == id(cls2))

    使用 metaclass 实现单例模式

    class Singleton(type):
        _instances = {}
        def __call__(cls, *args, **kwargs):
            if cls not in cls._instances:
                cls._instances[cls] = super(Singleton, cls).__call__(*args, **kwargs)
            return cls._instances[cls]
    
    class Cls4(metaclass=Singleton):
        pass
    
    cls1 = Cls4()
    cls2 = Cls4()
    print(id(cls1) == id(cls2))
    每天进步一点点,多思考,多总结 版权声明:本文为CNblog博主「zaituzhong」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
  • 相关阅读:
    adb 连接 Android 手机的两种方式
    Jmeter GUI及NON GUI下实现分布式
    史上最全最细 App 自动化环境部署
    不懂Java代码,照样把jmeter指定数据写入execl
    Dockerfile 让你轻松创建属于你的镜像 (下)
    Dockerfile 让你轻轻松松创建属于你的镜像 (上)
    Python vs Java (一):史上最全变量类型区别,99.99%的人都收藏了
    浏览器F12调试器定位系统前后端bug
    cookie,session
    App 抓包提示网络异常怎么破?(抓包HTTPS)
  • 原文地址:https://www.cnblogs.com/tingxin/p/12197904.html
Copyright © 2011-2022 走看看