• Python之单例模式


    单例模式基本概念
    '''
    1、什么是单例模式
        单例模式:基于某种方法实例化多次得到实例是同一个
    2、为何用单例模式
        当实例化多次得到的对象中存放的属性都一样的情况,应该将多个对象指向同一个内存地址,即同一个实例
    3、如何用
    '''

    一、使用类的方法

    # 单例模式实现一:
    """ 定义一个类,由类来调用,完成单例的调用过程"""
    #配置文件settings内容:
    """
    IP='0.0.0.1'
    PORT=3306
    """
    import settings
    class Mysql:
        __instance=None          #通过数据属性来记录用户调用类的方法实例化的状态,调用前状态为Nnoe
        def __init__(self,ip,port):
            self.ip=ip
            self.port=port
        #在类当中定义了一个类方法
        @classmethod
        def from_conf(cls):              #-----------------------将该方法装饰成由类来调用的方法,类来调用将类自动传入
            if cls.__instance is None:   #-----------------------判断该类是否是首次调用该方法,是则返回True
                cls.__instance=cls(settings.IP,settings.PORT)          #类从配置文件中读参数,实例化出的实例(实例即调用类产生的对象)
            #成立与否都返回,所以再外部返回,不用使用else,重复返回
            return cls.__instance        #-----------------------当该方法是第一次和不是第一次被类调用,则返回的结果均是cls.__instance
    #单例模式多次都用返回得到的是同一个内存地址
    obj1=Mysql.from_conf()               #-----------------------类来调用被装饰器装饰的该方法,将类当做第一个参数自动传入
    obj2=Mysql.from_conf()               #-----------------------实例化没有传参,直接从配置文件读,每次调用该方法,实例化的结果都一样,所以叫做单例
    obj3=Mysql.from_conf()               #单列模式的好处就是不用每次都进行传参
    print(obj1)
    print(obj2)
    print(obj3)
    print(obj1.__dict__)                  #{'ip': '0.0.0.1', 'port': 3306}-----从配置文件中类直接调用绑定给类的方法得到的结果
    
    obj4=Mysql('10.10.10.11',3307)        #直接调用类来是实例化,进行传参,对产生的对象进行初始化,可以和调用类的方法从配置文件中读得到形同的结果
    print(obj4)
    print(obj4.__dict__)                   #{'ip': '10.10.10.11', 'port': 3307},类直接传参,实例化得到的结果

    二、使用装饰器

    # 单例模式实现二:
    """自定义一个装饰器,由装饰器来完成单例的过程"""
    # 实例化的时候不传参,代表触发单例模式
    import settings
    '''--------------------------------------------------定义一个装饰器--------------------------------------------'''
    def singleton(cls):                                      #定义一个单例模式的函数,把类当做形参
        _instance=cls(settings.IP,settings.PORT)             #也可以方法类中cls. _instance=cls(settings.IP,settings.PORT)
        def wrapper(*args,**kwargs):
            if len(args)==0 and len(kwargs)==0: #Mysql不传参时,直接返回调用类拿到settings中的对象,如果调用类传参了,那么我们就返回类直接调用的产生对象的结果
                return _instance                             #cls._instance
            return cls(*args,**kwargs)                       #直接调用类(进行传参,对产生的随行进行初始化)的返回结果
        return wrapper
    '''--------------------------------------------------定义一个装饰器--------------------------------------------'''
    
    @singleton           #Mysql=singleton(Mysql) Mysql=wrapper-----没学类之前我们只学类用装饰器装饰函数,现在用自定义装饰器装饰类
    class Mysql:
        def __init__(self,ip,port):
            self.ip=ip
            self.port=port
    
    
    obj1=Mysql()                    #单例模式每次调用类不用为其进行传参,就如同为ATM的一些功能加上登录装饰器一样,每次登录执行这些功能,必须先登录
    obj2=Mysql()                    #不传参,每次调用时,就会执行自定义装饰器中的代码,就会从配置文件中读取内容:_instance=cls(settings.IP,settings.PORT)
    obj3=Mysql()
    print(obj1)                    #<__main__.Mysql object at 0x000002375BAC2E80>
    print(obj2)                    #<__main__.Mysql object at 0x000002375BAC2E80>
    print(obj3)                    #<__main__.Mysql object at 0x000002375BAC2E80>
    
    obj4=Mysql('0.0.0.3',3308)     #直接传参,经过装饰器时,会直接走:cls(*args,**kwargs) ,直接调用Mysql,对产生的对象obj4:进行初始化__init__(self,ip,port)
    print(obj4)                    #<__main__.Mysql object at 0x0000023762ADBF98>

    三、使用元类

    # 单例模式实现三
    """自定义一个元类,通过元类内的__call__来完成单例的过程"""
    # 基于元类不传参,从配置文件中读取相同的配置文件,传参则以自己传参的为准
    import settings
    class Mymeta(type):
        def __init__(self,class_name,class_basess,class_dic):                 #self=Mysql
            super(Mymeta,self).__init__(class_name,class_basess,class_dic)    #继承元类中的属性
            self.__instance=self.__new__(self)                                #造出Mysql的空对象
            self.__init__(self.__instance,settings.IP,settings.PORT)          #对Mysql的空对象从配置文件中传参进行初始化
    
        def __call__(self, *args, **kwargs):          #会在调用类这个对象是自动触发
            if len(args)==0 and len(kwargs)==0:       #判断如果不传参时,直接返回我们从配置文件中初始会的对象
                return self.__instance                #返回配置文件中初始化的对象
            # 否则即用户进行传参,而不是从配置文件中读取,那么我们就造一个空对象,然后对空对象那个进行初始化
            obj=self.__new__(self)                    #传参的结果:也是想初始化一个空对象
            self.__init__(obj,*args,**kwargs)         #会原封不动的接收调用类这个对象传进来的参数,完成对调用类产生的空对象的初始化
            return obj                                #将初始化的对象返回
    class Mysql(object,metaclass=Mymeta):
        def __init__(self,ip,port):
            self.ip=ip
            self.port=port
    
    
    obj1=Mysql()            #不传参直接调用类,产生对象,此时的对象,已经从配置文件中读取了配置信息,而非是一个空对象
    obj2=Mysql()            #每次调用该类读的是同一个配置文件,得到的对象的内存地址也是一样的
    obj3=Mysql()
    # 以上三者调用均是没有进行传参,调用类这个对象会触发__call__,会判断如果没有进行传参,则直接调用配置文件拿到返回的结果
    print(obj1)             #<__main__.Mysql object at 0x000002659486F2E8>
    print(obj2)
    print(obj3)
    
    obj4=Mysql('0.0.0.3',3308) #直接为类进行传参,进过判断就不会走配置文件了,而是直接造了一个空对象,然后对其进行初始化
    print(obj4)             #<__main__.Mysql object at 0x000002659B88BF98>
  • 相关阅读:
    rpc框架thrift
    rpc框架 SimpleXMLRP
    pyqt与拉勾网爬虫的结合
    python打造线程池
    python concurrent.futures包使用,捕获异常
    linux环境下pytesseract的安装和央行征信中心的登录验证码识别
    使用装饰器捕捉错误
    hbase 学习(十六)系统架构图
    大数据入门:各种大数据技术介绍
    How MapReduce Works
  • 原文地址:https://www.cnblogs.com/sui776265233/p/9254208.html
Copyright © 2020-2023  润新知