情景 1,某个服务器程序的配置信息存放在一个文件中,客户端通过一个 AppConfig 的类来读取配置文件的信息。如果在程序运行期间,有很多地方都需要使用配置文件的内容,也就是说,很多地方都需要创建 AppConfig 对象的实例,这就导致系统中存在多个 AppConfig 的实例对象,
而这样会严重浪费内存资源,尤其是在配置文件内容很多的情况下。事实上,类似 AppConfig 这样的类,我们希望在程序运行期间只存在一个实例对象。
/
/class Singleton:
#私有化 将类的对象私有化
__instance=None
#重写__new__ 开辟空间 要想对象不产生空间 我就在new中提前阻止他创建空间
def __new__(cls, *args, **kwargs):
print('-------我进new了---------')
if cls.__instance is None: #对象第一次调用类时 instance还是none 故先创建一个空间 ,当新对象再调用时 ,就会执行else方法了
print('---1')
cls.__instance=object.__new__(cls) #调用object的new方法 给一号对象创建一个新空间
return cls.__instance
else:
print('---2')
return cls.__instance #二号对象调用else,将老地址赋值给二号对象,因此二号对象和一号对象共同指向一个地址,所以单例模式的优势就体现出来了,同时只有一个类地址,而非单例模式的类每次被对象引用后都会创建一个地址
#return object.__new__() 阻止他创建空间就行
def __init__(self): #new方法中return的为cls.instance(这是个内存地址) 将cls.instance传给了self ,init中的self本来接收的就是地址
pass
s=Singleton()
s2=Singleton()
print(s)
print(s2,'\n')
结果为
-------我进new了---------
---1
-------我进new了---------
---2
<__main__.Singleton object at 0x00000271C866B9E8>
<__main__.Singleton object at 0x00000271C866B9E8>
事例2 第二个用new的单例模式
//
class Singleton:
#私有化 将类的对象私有化
__instance=None
name='类的name'
#重写__new__ 开辟空间 要想对象不产生空间 我就在new中提前阻止他创建空间
def __new__(cls, *args, **kwargs):
print('-------我进new了---------')
if cls.__instance is None: #对象第一次调用类时 instance还是none 故先创建一个空间 ,当新对象再调用时 ,就会执行else方法了
print('---1')
cls.__instance=object.__new__(cls) #调用object的new方法 给一号对象创建一个新空间
return cls.__instance
else:
print('---2')
return cls.__instance #二号对象调用else,将老地址赋值给二号对象,因此二号对象和一号对象共同指向一个地址,所以单例模式的优势就体现出来了,同时只有一个类地址,而非单例模式的类每次被对象引用后都会创建一个地址
#return object.__new__() 阻止他创建空间就行
def __init__(self): #new方法中return的为cls.instance(这是个内存地址) 将cls.instance传给了self ,init中的self本来接收的就是地址
pass
def show(self,n):
print('------------->show',Singleton.name,n)
s=Singleton()
s2=Singleton()
print(s)
print(s2)
print('---------------------------分割线-----------------------------')
s.show(5)
s2.show(7)
结果为
-------我进new了---------
---1
-------我进new了---------
---2
<__main__.Singleton object at 0x00000271C8671E48>
<__main__.Singleton object at 0x00000271C8671E48>
---------------------------分割线-----------------------------
------------->show 类的name 5
------------->show 类的name 7
单例模式装饰器必须要用到wraps装饰器
以下为wraps的介绍
装饰器的作用: 在不改变原有功能代码的基础上,添加额外的功能,如用户验证等。
@wraps(view_func)的作用: 不改变使用装饰器原有函数的结构(如name, doc)
1.不使用@wraps装饰器时候,看看__name__、__doc__输出的内容是什么
分析: 对test()方法进行装饰时候,实际上是 test = decorator(test)
#返回的是wrapper方法的引用,也就是让test指向了wrapper方法,所以调用test.name, 实际上是wrapper.name,
这样子可能会造成后面查找该方法的名字已经注释时候会得到装饰器的内嵌函数的名字和注释。
2. 使用@wraps装饰器解决这个问题
//
def decorator(func):
"""this is decorator __doc__"""
def wrapper(*args, **kwargs):
"""this is wrapper __doc__"""
print("this is wrapper method")
return func(*args, **kwargs)
return wrapper
@decorator
def test():
"""this is test __doc__"""
print("this is test method")
print("__name__: ", test.__name__)
print("__doc__: ", test.__doc__)
"""
结果:
__name__: wrapper
__doc__: this is wrapper __doc__
"""
# 分析: 对test()方法进行装饰时候,实际上是 test = decorator(test)
# 返回的是wrapper方法的引用,也就是让test指向了wrapper方法,所以调用test.__name__, 实际上是wrapper.__name__,
# 这样子可能会造成后面查找该方法的名字已经注释时候会得到装饰器的内嵌函数的名字和注释。
# 2. 使用@wraps装饰器解决这个问题
from functools import wraps
def decorator(func):
"""this is decorator __doc__"""
@wraps(func) #使用@wraps装饰器解决这个问题
def wrapper(*args, **kwargs):
"""this is wrapper __doc__"""
print("this is wrapper method")
return func(*args, **kwargs)
return wrapper
@decorator
def test():
"""this is test __doc__"""
print("this is test method")
print("__name__: ", test.__name__)
print("__doc__: ", test.__doc__) #输出文件开头注释的内容
"""
结果:
__name__: test
__doc__: this is test __doc__
"""
#用装饰器实现单例模式 装饰器可以修饰def 也可以修饰类
//
from functools import wraps
def Singleton(cls):
_instance={
}
@wraps(cls)
def _singleton(*args,**kwargs):
if cls not in _instance:
_instance[cls]=cls(*args,**kwargs) #典型的字典存储方式
return _instance[cls] #返回字典的values值
return _singleton
@Singleton
class Settings():
def __init__(self):
self.a='被修饰的方法'
self.b='xxxxx'
print(self.a)
s1=Settings()
s2=Settings()
print(s1,s2)
结果为
被修饰的方法
<__main__.Settings object at 0x000001E84DC71EF0> <__main__.Settings object at 0x000001E84DC71EF0>