设计模式-单例-Python实现

单例是什么?

【设计模式-单例-Python实现】单例模式,也叫单子模式,是一种常用的软件设计模式。在应用这个模式时,单例对象的类必须保证只有一个实例存在。许多时候整个系统只需要拥有一个的全局对象,这样有利于我们协调系统整体的行为。
维基百科-单例模式
简单来说,就是某种类,它有且就有一个实例。
在Python中怎么实现 重写__new__方法 __new__是类在创建时(不是实例化)时会调用的成员方法,其参数是这个类本身,即cls。这里我们使用hasattr方法来判断一个类有没有实例。如果没有就新建一个,有的话就返回当前的那个。这样就保证了这个类永远只会有一个实例。
# singleton class Singleton(object): def __new__(cls): if not hasattr(cls, '_instance'): cls._instance = super(Singleton, cls).__new__(cls) return cls._instanceclass MyClass(Singleton): a = 1A = MyClass() B = MyClass()print (A is B)

装饰器实现 这个方法的核心思想就是将对象的实例用其他的容器保存下来,每次实例类的时候,装饰器会判断这个类是不是已经在容器中了。如果是,则直接返回容器中的实例,否则则新建一个实例返回并放入容器中。容器中最多只会有一个值。
# singleton def singleton(cls): instances = {} def getinstance(*args, **kwargs): if cls not in instances: instances[cls] = cls(*args, **kwargs) return instances[cls] return getinstance@singleton class MyClass(): a = 1A = MyClass() B = MyClass()print (A is B)

用list 也可以
# singleton def singleton(cls): instances = [] def getinstance(*args, **kwargs): if not instances: instances.append(cls(*args, **kwargs)) return instances[0] return getinstance@singleton class MyClass(): a = 1A = MyClass() B = MyClass()#print (len(A)) print (A is B)

这样也可以
# singleton instances = None def singleton(cls): def getinstance(*args, **kwargs): global instances if not instances: instances = cls(*args, **kwargs) return instances return getinstance@singleton class MyClass(): a = 1A = MyClass() B = MyClass()#print (len(A)) print (A is B)

但是这样不行
# singleton def singleton(cls): instance = None def getinstance(*args, **kwargs): if not instance: instance = cls(*args, **kwargs) return instance return getinstance@singleton class MyClass(): a = 1A = MyClass() B = MyClass()#print (len(A)) print (A is B)

为什么?因为这里构成了闭包,Python只会会把闭包中用到的值保存下来,但是你不能在闭包中对其进行修改。也就是说在这个例子里,你只能访问instance,但是不能对其赋值,否则会报错UnboundLocalError。我会在另外一篇关于作用域和闭包的文章中仔细讲一讲。
怎么改呢?一种就是用上面的两种方法,将它改成一个列表或者字典,我们不能对列表本身做修改,但是可以对列表中包含的对象做修改;另一种方法则是用关键词nonlocal:
# singleton def singleton(cls): instance = None def getinstance(*args, **kwargs): nonlocal instance if not instance: instance = cls(*args, **kwargs) return instance return getinstance@singleton class MyClass(): a = 1A = MyClass() B = MyClass()#print (len(A)) print (A is B)

    推荐阅读