单例模式
单例模式即某个类只会生成一个实例,即使多次生成实例也只会返回同一个对象的引用。实现方式是重写类的__new__方法。
__init__和__new__的区别
__new__ :生成类的实例,分配对象的内存。
__init__:对对象进行初始化,设置属性初始值等等。
super()
首先看一下如果我们重写的__new__方法不做任何操作会如何。
1 class Foo: 2 def __new__(cls, *args, **kwargs): 3 pass 4 5 if __name__ == ‘__main__‘: 6 a = Foo() 7 print(a)
输出:
None
重写了__new__方法没有返回任何对象,此时类实例无法生成。因此,我们重写的__new__方法必须和原来的方法一样返回一个类实例。
super()方法可以调用父类的方法,在重写__new__方法时,通过调用super().__new__(cls)来生成类实例。
class Foo: def __new__(cls, *args, **kwargs): return super().__new__(cls) if __name__ == ‘__main__‘: a = Foo() print(a)
输出:
<__main__.Foo object at 0x000002755D4CE610>
类中保存实例对象,实现单例
在前文的基础上,生成多个实例,分别观察地址。
obj = Foo() print(id(obj)) obj = Foo() print(id(obj)) obj = Foo() print(id(obj)) 输出: 2390878971408 2390879026192 2390878971408
可以看到生成的多个实例地址均不相同,说明多个实例各不相同。下面开始实现单例。
进一步修改__new__方法。
__new__第一次被调用的时候,就在类中对生成的实例进行保存,再次被调用的时候则返回保存的实例,故实现单例。
class Foo: instance = None def __new__(cls, *args, **kwargs): if cls.instance == None: cls.instance = super().__new__(cls) return cls.instance
在此基础之上,再观察多次生成的实例地址。此时多次调用生成的实例地址均相同,说明此时引用的是同一实例。
obj = Foo() print(id(obj)) obj = Foo() print(id(obj)) obj = Foo() print(id(obj)) 输出: 2094013594496 2094013594496 2094013594496