单例是什么?
单例模式,也叫单子模式,是一种常用的软件设计模式。在应用这个模式时,单例对象的类必须保证只有一个实例存在。许多时候整个系统只需要拥有一个的全局对象,这样有利于我们协调系统整体的行为。
简单来说,就是某种类,它有且就有一个实例。
在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._instance
class MyClass(Singleton):
a = 1
A = 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 = 1
A = 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 = 1
A = 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 = 1
A = 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 = 1
A = 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 = 1
A = MyClass()
B = MyClass()
#print (len(A))
print (A is B)
网友评论