New implementation and decorator implementation of python singleton mode

Scenario 1, the configuration information of a certain server program is stored in a file, and the client reads the configuration file information through an AppConfig class. If during the running of the program, there are many places where the content of the configuration file needs to be used, that is, many places need to create an instance of the AppConfig object, which leads to multiple instances of AppConfig in the system,
and this will seriously waste memory Resources, especially when the content of the configuration file is large. In fact, for classes like AppConfig, we hope that only one instance object exists during the running of the program.

/
/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> 

Case 2 The second singleton mode with 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

Singleton mode decorator must use wrap decorator. The
following is an introduction to wraps
. The role of decorator: On the basis of not changing the original function code, additional functions such as user authentication are added.
The role of @wraps(view_func): does not change the structure of the original function using the decorator (such as name, doc)
1. When not using the @wraps decorator, see what the output of __name__ and __doc__ is

Analysis: When decorating the test() method, it is actually test = decorator(test)

#Returned is the reference of the wrapper method, that is, let test point to the wrapper method, so call test. name , which is actually wrapper. name ,
which may cause the decorator to be obtained when the name of the method is found later when it is annotated The name and comment of the embedded function.
2. Use @wraps decorator to solve this problem

// 
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__

"""


#Use decorators to implement singleton mode. Decorators can modify def or class

//
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>

Guess you like

Origin blog.csdn.net/weixin_43516990/article/details/108905035