0.单例介绍
在使用类创建对象的时候,每次都会调用__new__()方法创建一个新的对象并调用__init__()方法对实例对象进行初始化,单例模式即不管创建了多少次,都只产生唯一的实例对象。可以在调用new方法前验证是否之前创建过实例对象,如果创建过则返回该对象
1.使用__new__()方法创建单例
class Singleton(object):
def __init__(self):
pass
def __new__(cls, *args, **kwargs):
# hasatter() 判断一个对象是否有某个属性
if not hasattr(cls, "_instance"):
cls._instance = super().__new__(cls, *args, **kwargs)
return cls._instance
print(Singleton() is Singleton()) # True
该方式的init初始化可以被覆盖
class Singleton(object):
def __init__(self,name):
self.name = name
def __new__(cls, *args, **kwargs):
# hasatter() 判断一个对象是否有某个属性
if not hasattr(cls, "_instance"):
cls._instance = super().__new__(cls)
return cls._instance
a1 = Singleton("zhangsan")
a2 = Singleton("lisi")
print(a1 is a2) # True
print(a1.name) # zhangsan
print(a2.name) # lisi
2.使用元类的__call__()方法
元类(metaclass),只有继承了type的类才可以作为元类被继承,所有的用户定义类,都是type类的实例(ps:object是type类的实例,同时也是type的基类)。
# 正常定义类
class MyClass:
data = 1
# Python 真正执行的是下面这段代码:
class = type(classname, superclasses, attributedict)
# 这里等号右边的type(classname, superclasses, attributedict),就是 type 的__call__运算符重载,它会进一步调用:
type.__new__(typeclass, classname, superclasses, attributedict)
type.__init__(class, classname, superclasses, attributedict)
因此可以创建一个单例元类,想要实现单例的类直接继承该元类
class Singleton(type):
_instace = {}
def __call__(cls, *args, **kwargs):
if cls not in cls._instace:
cls._instace[cls] = super().__call__(*args, **kwargs)
return cls._instace[cls]
class A(metaclass=Singleton):
def __init__(self,name):
self.name = name
a1 = A("zhangsan")
a2 = A("lisi")
print(a1 is a2) # True
print(a1.name) # zhangsan
print(a2.name) # zhangsan
3.使用装饰器
def singleton(cls):
instances = {}
def _singleton(*args, **kwargs):
if cls not in instances:
instances[cls] = cls(*args, **kwargs)
return instances[cls]
return _singleton
@singleton
class A:
pass
print(A() is A()) # True
4.模块单例
Python 的模块就是天然的单例模式,因为模块在第一次导入时,会生成 .pyc 文件,当第二次导入时,就会直接加载 .pyc 文件,而不会再次执行模块代码。
# single.py
class Singleton:
pass
singleton = Singleton()
# other.py
from single import singleton