• Python之单例对象的应用


    今天来讲一下单例对象的使用。

    单例对象模式

     单例对象模式是一种常用的软件设计模式,这种模式保证了某一个类只能有一个实例化的对象存在。当我们希望在整个程序中某个类只能有一个实例时,就可以用到这个单例模式。

    单例模式的实现方法

    使用__new__方法

    使用__new__方法可以限制类只能被实例化一次,直接就用下面的方法来定义就行了

    class Singleton(object):
        _instance = None
    
        def __new__(cls,*args,**kwargs):
            if not cls._instance:
                cls._instance = super(Singleton,cls).__new__(cls,*args,**kwargs)
    
            return cls._instance

    当我们在第一次对这个类实例化一个对象的时候,类变量_instnce就会被赋值为新的对象,而再次实例化的时候cls._instance是有值的,就不会重新实例化一个新的对象。我们可以通过id来判定一下效果

    a = Singleton()
    b = Singleton()
    
    print(id(a))
    print(id(b))
    
    ########输出########
    139968970404024
    139968970404024

    也就是说分别实例化的a和b其实是一个对象。

    使用模块

    Python的模块导入就是天然的单例模式,因为模块在第一次导入的时候就会生成一个.pyc文件,当第二次导入的 时候,就会先从pyc文件中找是否倒入过,如果以前导入过这个模块,就不再执行导入的过程。所以我们把需要的对象在模块中实例化以后导入给需要的脚本中,就是单例对象。
    我们现在有个脚本文件里面定义了一个类,并且对这个类做了一个实例化

    #mysingleton.py
    class Animal(object):
        def run(self):
            print('running...')
    
    
    a = Animal()

    那么在另一个脚本中,我们把这个实例化后的对象导入一下

    #main.py
    from mysingleton import a
    
    a.run()

    因为这个对象a只能被导入一次,如果一个程序是由很多的脚本文件组成的,只要有一个文件导入了这个对象a,那么这个a不管在哪个脚本中被导入其实都是一个对象,即便是换了一个名称

    #main.py
    from mysingleton import a as a1
    
    print('a1',id(a1))
    
    from mysingleton import a as a2
    
    print('a2',id(a2))
    
    ##########输出##########
    a1 140212539471856
    a2 140212539471856

    或者是有多个py脚本

    #mysingleton.py
    class Animal(object):
        def run(self):
            print('running...')
    
    
    a = Animal()

    有一个文件调用了这个变量a

    #funcs.py
    from mysingleton import a
    
    def fun():
        print('in fun a:',id(a))

    还有一个文件导入了这个fun

    #main.py
    from mysingleton import a
    import funcs
    funcs.fun()
    print('in main a',id(a))

    最后运行的结论会是什么样的呢?

    ##########输出##########
    in fun a: 139630131360320
    in main a 139630131360320

    所以这两个脚本里导入 的一个对象就是单例对象。但是要注意的是我们导入的是一个实例化以后的对象,如果仅仅是导入类以后再在脚本中实例化那么就不是单例变量了

    #main.py
    from mysingleton import Animal
    a = Animal()
    b = Animal()
    
    print('a',id(a))
    print('b',id(b))

    在上面的例子中,a和b就是一般的实例化的两个对象。

    使用装饰器

     这个大致看一下就行了,不作为主要的知识点

    def Singleton(cls):
        _instance = {}
    
        def _singleton(*args,**kwargs):
            if cls not in _instance:
                _instance[cls] = cls(*args,**kwargs)
            return _instance[cls]
    
        return _singleton
    
    
    @Singleton
    class A(object):
        def fun(self):
            pass
    
    a = A()
    b = A()
    
    print('a',id(a))
    print('b',id(b))

     还有一种方式是使用metaclass元类,但是有些多线程的环境下会发生一些问题,我们这里就先不讲了。

  • 相关阅读:
    WinDbg常用命令系列---线程相关操作~*
    WinDbg常用命令系列---?*
    使用WinDbg调试入门(内核模式)
    java基础-stringAPI
    springboot-集成WebSockets广播消息
    sprincloud-Feign配置二
    springcloud-Feign配置一
    springboot-集成jdbcTemplate
    spingboot2.x集成单元测试
    springboot跨域CORS处理
  • 原文地址:https://www.cnblogs.com/yinsedeyinse/p/13254379.html
Copyright © 2020-2023  润新知