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>
以上是 Python之单例模式 的全部内容, 来源链接: utcz.com/z/388371.html