我正在尝试在下面的代码中应用Singleton设计模式
class SMSMgr( object ):
_instance = None
def __init__(self):
self._allsp = []
def __new__(cls, *args, **kwargs):
if not cls._instance:
cls._instance = super(SMSMgr, cls).__new__(
cls, *args, **kwargs)
return cls._instance
def loadsettings(self):
get_all_sp = ServiceProvider.objects.filter(status = False)
for obj in get_all_sp:
cla = obj.class_Name
a=globals()[str(obj.class_Name)](obj.userName,obj.password,obj.sendingurl)
self._allsp.append(a)
#print self._allsp
def send(self):
print "+++++++++++++++++++== Global send "
if __name__ == "__main__":
b = SMSMgr()
b.loadsettings()
print b._allsp
print "b end -------------------"
c = SMSMgr()
c.loadsettings()
print c._allsp
print "c end -------------------"
根据singleton b对象应该与c对象相同。
但是,当我运行上面的代码时,我得到b
和c
的不同对象
请建议我如何以单身人士的身份做这件事。
答案 0 :(得分:2)
你的单身模式看起来应该对我有用。是否可能因为__init__
被调用两次,当您创建新实例时,self._allsp
会重置,使您看起来有新实例?
您可以通过输入以下内容来检查它们是否实际上是同一个实例:
print b is c
在脚本的末尾。 (如果它们是相同的,它将打印True
我能想到的最简单的解决方法是将_allsp
作为类属性并将其从__init__
中删除。 e.g。
class SMSMgr( object ):
_instance = None
_allsp = []
def __init__(self):
pass
以下是一些经过测试的代码,它按照我的描述创建了一个单例:
class SMSMgr( object ):
_instance = None
_allsp = []
def __init__(self):
pass
def __new__(cls, *args, **kwargs):
if not cls._instance:
cls._instance = super(SMSMgr, cls).__new__(
cls, *args, **kwargs)
return cls._instance
def foo(self,arg):
self._allsp.append(arg)
def bar(self):
print self._allsp
a = SMSMgr()
a.foo(1)
b = SMSMgr()
b.foo(2)
a.bar()
b.bar()
print a is b
答案 1 :(得分:0)
我很确定这里的问题是你的__init__
没有标记,所以即使每个实例化返回同一个对象,每次都会重新运行__init__
。你可以尝试这样的事情:
def __init__(self):
if not hasattr(self, '_allsp'):
self._allsp = []
虽然对于更强大的解决方案,您可能需要更类似的内容:
def __init__(self):
if not hasattr(self.__class__, 'inited'):
self._allsp = []
self.__class__.inited = True
请注意,除非将init功能包装在某种锁中,否则这不是线程安全的。
正如@mgilson在他的回答中所说,如果你试图在Python中创建一个单例,你可能应该只使用类属性而不是实例属性,并查看它是否有意义为类完全分开开始,或将其折叠到其他非单身类。还有一种模式,borg pattern,当singetons和Python出现在同一段中时经常被提及。