0

我正在尝试在下面的代码中应用单例设计模式

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 -------------------"

根据单例 b 对象应与 c 对象相同。但是当我运行上面的代码时,我得到了不同的对象bc 请建议我如何以单身人士的身份做到这一点。

4

2 回答 2

2

你的单例模式看起来应该对我有用。是否有可能因为__init__两次都被调用,所以当您创建一个新实例时,self._allsp会被重置,从而看起来您有一个新实例?

您可以通过放置以下内容来检查它们是否实际上是同一个实例:

print b is c

在脚本的末尾。True(如果它们相同,它将打印)

我能想到的最简单的修复方法是创建_allsp一个类属性并将其从__init__. 例如

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
于 2013-02-05T14:39:10.627 回答
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 模式,当 singetons 和 Python 在同一段中被提及时,它经常被提及。

于 2013-02-05T14:41:29.163 回答