在Python中似乎有很多方法来定义单例对象。对Stack Overflow是否有一致的意见?


当前回答

模块方法工作得很好。如果我绝对需要一个单例,我更喜欢元类方法。

class Singleton(type):
    def __init__(cls, name, bases, dict):
        super(Singleton, cls).__init__(name, bases, dict)
        cls.instance = None 

    def __call__(cls,*args,**kw):
        if cls.instance is None:
            cls.instance = super(Singleton, cls).__call__(*args, **kw)
        return cls.instance

class MyClass(object):
    __metaclass__ = Singleton

其他回答

模块方法工作得很好。如果我绝对需要一个单例,我更喜欢元类方法。

class Singleton(type):
    def __init__(cls, name, bases, dict):
        super(Singleton, cls).__init__(name, bases, dict)
        cls.instance = None 

    def __call__(cls,*args,**kw):
        if cls.instance is None:
            cls.instance = super(Singleton, cls).__call__(*args, **kw)
        return cls.instance

class MyClass(object):
    __metaclass__ = Singleton

正如公认的答案所说,最常用的方法是只使用一个模块。

考虑到这一点,下面是一个概念的证明:

def singleton(cls):
    obj = cls()
    # Always return the same object
    cls.__new__ = staticmethod(lambda cls: obj)
    # Disable __init__
    try:
        del cls.__init__
    except AttributeError:
        pass
    return cls

有关__new__的更多详细信息,请参阅Python数据模型。

例子:

@singleton
class Duck(object):
    pass

if Duck() is Duck():
    print "It works!"
else:
    print "It doesn't work!"

注:

为此,您必须使用new-style类(派生自object)。 单例在定义时初始化,而不是在第一次使用时初始化。 这只是一个简单的例子。我从未在产品代码中实际使用过它,也不打算这样做。

在Python中实现单例的一个稍微不同的方法是Alex Martelli(谷歌员工和Python天才)的borg模式。

class Borg:
    __shared_state = {}
    def __init__(self):
        self.__dict__ = self.__shared_state

因此,它们共享状态,而不是强制所有实例具有相同的标识。

有一次我用Python写了一个单例,我使用了一个类,其中所有成员函数都有classmethod装饰器。

class Foo:
    x = 1
  
    @classmethod
    def increment(cls, y=1):
        cls.x += y

如果你想继续装饰(注释)类,创建一个单例装饰器(又名注释)是一种优雅的方式。然后将@singleton放在类定义之前。

def singleton(cls):
    instances = {}
    def getinstance():
        if cls not in instances:
            instances[cls] = cls()
        return instances[cls]
    return getinstance

@singleton
class MyClass:
    ...