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


当前回答

class Singeltone(type):
    instances = dict()

    def __call__(cls, *args, **kwargs):
        if cls.__name__ not in Singeltone.instances:            
            Singeltone.instances[cls.__name__] = type.__call__(cls, *args, **kwargs)
        return Singeltone.instances[cls.__name__]


class Test(object):
    __metaclass__ = Singeltone


inst0 = Test()
inst1 = Test()
print(id(inst1) == id(inst0))

其他回答

如果你不想要上面的基于元类的解决方案,并且你不喜欢简单的基于函数装饰器的方法(例如,因为在这种情况下,单例类上的静态方法将不起作用),这种妥协是可行的:

class singleton(object):
  """Singleton decorator."""

  def __init__(self, cls):
      self.__dict__['cls'] = cls

  instances = {}

  def __call__(self):
      if self.cls not in self.instances:
          self.instances[self.cls] = self.cls()
      return self.instances[self.cls]

  def __getattr__(self, attr):
      return getattr(self.__dict__['cls'], attr)

  def __setattr__(self, attr, value):
      return setattr(self.__dict__['cls'], attr, value)

我认为强制一个类或实例为单例是多余的。就我个人而言,我喜欢定义一个普通的可实例化类、一个半私有引用和一个简单的工厂函数。

class NothingSpecial:
    pass

_the_one_and_only = None

def TheOneAndOnly():
    global _the_one_and_only
    if not _the_one_and_only:
        _the_one_and_only = NothingSpecial()
    return _the_one_and_only

或者如果在模块第一次导入时实例化没有问题:

class NothingSpecial:
    pass

THE_ONE_AND_ONLY = NothingSpecial()

通过这种方式,您可以针对新的实例编写测试,而不会产生副作用,并且不需要在模块中添加全局语句,如果需要,您可以在将来派生变体。

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

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

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的新手,我不确定最常见的习语是什么,但我能想到的最简单的事情就是使用模块而不是类。类中的实例方法变成了模块中的函数,任何数据都变成了模块中的变量,而不是类的成员。我怀疑这是解决人们使用单例对象的问题的python方法。

如果你真的想要一个单例类,有一个合理的实现描述在谷歌的第一个点击“Python singleton”,具体地说:

class Singleton:
    __single = None
    def __init__( self ):
        if Singleton.__single:
            raise Singleton.__single
        Singleton.__single = self

这似乎奏效了。

谷歌Testing博客上也有一些有趣的文章,讨论了为什么单例是/可能是不好的,并且是一种反模式:

单身人士是病态的说谎者 单身人士都去哪儿了? 单身的根本原因