方式一:mysql
# 單例模式: # 實現目的:實例化屢次,獲得的實例是同一個,就是同一個對象,同一個名稱空間(更加節省空間) ####################################方式一:在類內部定義一個類方法################################# import settings class Mysql: __instance=None #定義一個變量,來接收實例化對象,方便下面作判斷 def __init__(self,ip,port): self.ip=ip self.port=port # @classmethod #作成類方法 #綁定給Mysql類去直接調用實例化 def from_conf(cls): #目的是要調取mysql這個類經過從配置文件讀取IP、端口參數,完成調用init方法,拿到一個實例化init方法的對象 # mysql(settings.IP,settings.PORT) #若是是這樣每次,實例化出的對象,都是不一樣的名稱空間,可是數據是同一份 # return cls(settings.IP,settings.PORT) #cls(ip,port) 就是調用init方法 #演變最終版:思考能夠統必定義一個初始變量__instance=None,將第一次實例的對象傳給他,有每次外面再訪問就直接 if cls.__instance is None: cls.__instance=cls(settings.IP,settings.PORT) return cls.__instance #以前版本: # p1=Mysql.from_conf() # print(p1) #<__main__.Mysql object at 0x02BE82B0> #數據是同一份,但每次實例化,指向的都是不一樣的內存地址 # p2=Mysql.from_conf() # print(p2) #<__main__.Mysql object at 0x02C1AB90> #這樣寫就完美的實現了隔離: #升級版本後,能夠實現,訪問存的東西同樣的,能夠指向同一個內存空間 obj=Mysql.from_conf() print(obj.__dict__) #也能夠傳入新的參數,另外新造一個名稱空間 obj2=Mysql('3.3.3.3',8888) print(obj2.__dict__)
方式二:sql
#方式二:裝飾器 import settings def singleton(cls): __instance=cls(settings.IP,settings.PORT) #給Mysql的init方法傳參,實例化獲得一個對象,__instance def wrapper(*args,**kwargs): #判斷外面調用時,是否有傳值進來 if len(args) == 0 and len(kwargs)== 0: return __instance #用戶沒有傳傳參,意思直接返回默認settings的值 return cls(*args,**kwargs) #不然會建立新的值 return wrapper @singleton class Mysql: ##Mysql=singleton(Mysql) #Mysql=wrapper def __init__(self,ip,port): self.ip=ip self.port=port def aa(self): print('IP地址:%s 端口:%s'%(self.ip,self.port)) #實現的結果是:想要實現的是mysql不傳參數,默認指向同一個實例 #沒有傳參數的調用:保證每次實例化獲得的是同一個內存地址 obj1=Mysql() #wrapper() obj2=Mysql() #wrapper() print(obj1.__dict__,id(obj)) #{'ip': '1.1.1.1', 'port': 3306} 45554896 print(obj2.__dict__,id(obj)) #{'ip': '1.1.1.1', 'port': 3306} 45554896 #有傳參的狀況下,建立新的 obj2=Mysql('2.2.2.2',666) print(obj2.__dict__)
方式三:app
方式三:自定義元類 #自定義元類控制類的調用過程,即類的實例化:__call__ import settings class Mymeta(type): #init在定義類時就已經建好了 def __init__(self,class_name,class_bases,class_dic): #造Mysql空對象,調類中init方法,繼承父類,造一個空對象 super(Mymeta,self).__init__(class_name,class_bases,class_dic) # obj=self.__new__(self) #造出一個mysql的空對象 # # self.__init__(obj,settings.IP,settings.PORT) #w從配置文件中加載配置完成Mysql對象的初始化 # # self.__instance=obj #賦值操做 # self.__instance=self.__new__(self) #先造一個空對象 __instance self.__init__(self.__instance,settings.IP,settings.PORT) #爲空的對象初始化獨有的屬性 print(self.__instance.__dict__) #這一步剛剛造完類,還沒運行代碼就已經造好了一個空對象,保存到類屬性中 def __call__(self, *args, **kwargs): #在調用類時才運行 if len(args)==0 and len(kwargs)==0:
#思考應該 return 一個已經建立好的Mysql的對象
#由於call方法只有在調用時才觸發,可是要在調用前就應該建立好一個Mysql的對象 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 #拿到的是同一個內存空間地址 obj=Mysql() obj1=Mysql() obj2=Mysql() print(obj) print(obj1) print(obj2) #拿到是單獨的內存地址 obj2=Mysql('3.3.3.3',8888) print(obj2.__dict__)
注意:
1.Mysql的調用時才運行__call__ (控制的是類Mysql的調用過程,就是類mysql的實例化過程)
2.__init__(控制類Mysql這個對象的產生過程,就是類Mymeta的實例化過程)