python-单例模式
当我们创建一个类时,有时并希望每次使用类时都创建一个不同的实例对象浪费资源(如mysql的数据库连接同一个数据库时参数是一样的),我们可以使用单例模式
一、懒汉式–创建单例对象
在真正需要使用对象时才去创建该单例类对象。
懒汉式创建对象的方法是在程序使用对象前,先判断该对象是否已经实例化(判空),若已实例化直接返回该类对象。,否则则先执行实例化操作。
1.单例模式-单线程使用
原理:重写python构造函数,先创建一个类变量初始值为None,再判断该对象是否已经实例化(判断该对象是否为None)。
若未实例化则把实例化对象赋值给类变量,后返回该类变量。
若已实例化则直接返回第一次创建的实例化对象。
class MySql:
instance = None
def __init__(self, host):
pass
def __new__(cls, *args, **kwargs):
if cls.instance: # 判断实例对象是否已经被创建-如果没创建则创建,如果创建直接返回原来的实例对象
return cls.instance
cls.instance = object.__new__(cls) # 创建空对象
return cls.instance
if __name__ == '__main__':
mysql_1 = MySql('localhost')
mysql_2 = MySql('localhost')
print(mysql_1)
print(mysql_2)
执行结果
<__main__.MySql object at 0x0000026E3BAB5668>
<__main__.MySql object at 0x0000026E3BAB5668>
2.单例模式-可供多线程使用
我们在以上程序中继续完善程序-为避免多线程调用时出现问题,所以在重写构造函数时加线程锁,为避免每次申请锁消耗资源所以在上面再加一层判断。
import threading
lock = threading.Lock()
class MySql:
instance = None
def __init__(self, host):
pass
def __new__(cls, *args, **kwargs):
if cls.instance: # 提升性能-为避免每次查看锁消耗资源所以在上面再加一层判断
return cls.instance
with lock: # 加锁
if cls.instance: # 判断实例对象是否已经被创建-如果没创建则创建,如果创建直接返回原来的实例对象
return cls.instance
cls.instance = object.__new__(cls) # 创建空对象
return cls.instance
if __name__ == '__main__':
mysql_1 = MySql('localhost')
mysql_2 = MySql('localhost')
print(mysql_1)
print(mysql_2)
执行结果
<__main__.MySql object at 0x0000022BDC2447F0>
<__main__.MySql object at 0x0000022BDC2447F0>
二、饿汉式–创建单例对象
饿汉式在类加载时已经创建好该对象,在程序调用时直接返回该单例对象即可,即我们在编码时就已经指明了要马上创建这个对象,不需要等到被调用时再去创建,当其他程序要使用时直接调用该实例对象即可
class MySql:
def __init__(self, host):
pass
def test(self):
pass
mysql = MySql()
if __name__ == '__main__':
print(mysql)
# 其他程序不需要再创建实例直接调用已创建好的实例对象即可
执行结果
<__main__.MySql object at 0x000001EC40EA2470>