类正在返回两个不同的对象

时间:2013-02-05 14:34:42

标签: python django

我正在尝试在下面的代码中应用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对象相同。 但是,当我运行上面的代码时,我得到bc的不同对象 请建议我如何以单身人士的身份做这件事。

2 个答案:

答案 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出现在同一段中时经常被提及。