Python之单例模式

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

回到顶部