有没有简单,优雅的方式来定义单身人士?

似乎有很多方法可以在Python中定义单例 。 关于Stack Overflow是否有共识?

我真的不明白需要,因为具有函数(而不是类)的模块可以很好地用作单例。 它的所有variables都将被绑定到模块,无论如何都不能重复实例化。

如果你想使用一个类,就没有办法在Python中创build私有类或私有构造函数,所以你不能保护多个实例,除了通过使用你的API的惯例。 我仍然只是将方法放在模块中,并将模块视为单例。

这是我自己实现的单身人士。 你所要做的就是装饰课堂。 得到单身人士,然后你必须使用Instance方法。 这是一个例子:

 @Singleton class Foo: def __init__(self): print 'Foo created' f = Foo() # Error, this isn't how you get the instance of a singleton f = Foo.Instance() # Good. Being explicit is in line with the Python Zen g = Foo.Instance() # Returns already created instance print f is g # True 

这里是代码:

 class Singleton: """ A non-thread-safe helper class to ease implementing singletons. This should be used as a decorator -- not a metaclass -- to the class that should be a singleton. The decorated class can define one `__init__` function that takes only the `self` argument. Also, the decorated class cannot be inherited from. Other than that, there are no restrictions that apply to the decorated class. To get the singleton instance, use the `Instance` method. Trying to use `__call__` will result in a `TypeError` being raised. """ def __init__(self, decorated): self._decorated = decorated def Instance(self): """ Returns the singleton instance. Upon its first call, it creates a new instance of the decorated class and calls its `__init__` method. On all subsequent calls, the already created instance is returned. """ try: return self._instance except AttributeError: self._instance = self._decorated() return self._instance def __call__(self): raise TypeError('Singletons must be accessed through `Instance()`.') def __instancecheck__(self, inst): return isinstance(inst, self._decorated) 

你可以像这样覆盖__new__方法:

 class Singleton(object): _instance = None def __new__(cls, *args, **kwargs): if not cls._instance: cls._instance = super(Singleton, cls).__new__( cls, *args, **kwargs) return cls._instance if __name__ == '__main__': s1 = Singleton() s2 = Singleton() if (id(s1) == id(s2)): print "Same" else: print "Different" 

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

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

因此,不要强迫所有实例具有相同的身份,而是共享状态。

模块方法运作良好。 如果我绝对需要单身,我更喜欢Metaclass方法。

 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 

从PEP318中看到这个实现,用装饰器实现单例模式:

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

正如接受的答案所说,最习惯的方式就是使用一个模块

考虑到这一点,这是一个概念certificate:

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

笔记:

  1. 你必须使用新的类(派生自object )。

  2. 单例在被定义时被初始化,而不是第一次被使用。

  3. 这只是一个玩具的例子。 我从来没有真正使用过这个生产代码,并且不打算。

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

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

我对此很不确定,但是我的项目使用了“常规单例”(不是强制的单例),也就是说,如果我有一个名为DataController的类,我将它定义在同一个模块中:

 _data_controller = None def GetDataController(): global _data_controller if _data_controller is None: _data_controller = DataController() return _data_controller 

这是不完美的,因为它是一个完整的六行。 但是,我所有的单身人士都使用这种模式,至less是非常明确的(这是pythonic)。

创build一个单例装饰器(又名注释)是一种优雅的方式,如果你想装饰(注释)类向前。 那么你只需在你的类定义之前加上@singleton。

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

在Googletesting博客上也有一些有趣的文章,讨论为什么单身人士可能是坏的,而且是反模式:

  • 单身人士是病理性的说谎者
  • 所有的单身人士都去哪了?
  • 单身人士的根本原因

Python文档涵盖了这个:

 class Singleton(object): def __new__(cls, *args, **kwds): it = cls.__dict__.get("__it__") if it is not None: return it cls.__it__ = it = object.__new__(cls) it.init(*args, **kwds) return it def init(self, *args, **kwds): pass 

我可能会重写它看起来更像这样:

 class Singleton(object): """Use to create a singleton""" def __new__(cls, *args, **kwds): """ >>> s = Singleton() >>> p = Singleton() >>> id(s) == id(p) True """ self = "__self__" if not hasattr(cls, self): instance = object.__new__(cls) instance.init(*args, **kwds) setattr(cls, self, instance) return getattr(cls, self) def init(self, *args, **kwds): pass 

这应该是相对干净的:

 class Bus(Singleton): def init(self, label=None, *args, **kwds): self.label = label self.channels = [Channel("system"), Channel("app")] ... 

这里是Peter Norvig的Python IAQ的一个例子我如何在Python中进行Singleton模式? (你应该使用浏览器的searchfunction来find这个问题,没有直接的联系,抱歉)

另外,Bruce Eckel在他的“ Thinking in Python”一书中也有另外一个例子(同样没有直接链接到代码)

我认为强迫一个类或一个实例成为一个单例是过分的。 我个人喜欢定义一个普通的可实例化的类,一个半私有的引用和一个简单的工厂函数。

 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() 

这样,你可以编写新的实例没有副作用的testing,并且没有必要使用全局语句来散布模块,如果需要的话,你可以在将来派生变体。

用Python实现的Singleton模式由ActiveState提供。

看起来诀窍是把这个应该只有一个实例的类放在另一个类的内部。

 class Singleton(object[,...]): staticVar1 = None staticVar2 = None def __init__(self): if self.__class__.staticVar1==None : # create class instance variable for instantiation of class # assign class instance variable values to class static variables else: # assign class static variable values to class instance variables 

我简单的解决scheme是基于函数参数的默认值。

 def getSystemContext(contextObjList=[]): if len( contextObjList ) == 0: contextObjList.append( Context() ) pass return contextObjList[0] class Context(object): # Anything you want here 

对于Python来说相对陌生,我不确定最常用的习惯用法是什么,但我能想到的最简单的方法就是使用模块而不是类。 你的类的实例方法会变成模块中的函数,而任何数据只是模块中的variables而不是类的成员。 我怀疑这是pythonic方法来解决人们使用单身人士的问题types。

如果你真的想要一个singleton类,那么在Google的第一个命令 “Python singleton”中有一个合理的实现,特别是:

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

这似乎是伎俩。

好吧,我知道,单身人士可能是好的或坏的。 这是我的实现,我只是扩展了一个经典的方法来引入一个caching里面,并产生了许多不同types的实例,或许多相同types的实例,但具有不同的参数。

我把它称为Singleton_group,因为它将类似的实例组合在一起,并防止可以创build具有相同参数的同一个类的对象:

 # Peppelinux's cached singleton class Singleton_group(object): __instances_args_dict = {} def __new__(cls, *args, **kwargs): if not cls.__instances_args_dict.get((cls.__name__, args, str(kwargs))): cls.__instances_args_dict[(cls.__name__, args, str(kwargs))] = super(Singleton_group, cls).__new__(cls, *args, **kwargs) return cls.__instances_args_dict.get((cls.__name__, args, str(kwargs))) # It's a dummy real world use example: class test(Singleton_group): def __init__(self, salute): self.salute = salute a = test('bye') b = test('hi') c = test('bye') d = test('hi') e = test('goodbye') f = test('goodbye') id(a) 3070148780L id(b) 3070148908L id(c) 3070148780L b == d True b._Singleton_group__instances_args_dict {('test', ('bye',), '{}'): <__main__.test object at 0xb6fec0ac>, ('test', ('goodbye',), '{}'): <__main__.test object at 0xb6fec32c>, ('test', ('hi',), '{}'): <__main__.test object at 0xb6fec12c>} 

每个对象携带单身caching…这可能是邪恶的,但它对一些:)

辛格尔顿的兄弟

我完全同意staale,我在这里留下一个创build单身半兄弟的例子:

 class void:pass a = void(); a.__class__ = Singleton 

即使看起来不像它,现在也会报告与单身人员是同一class级。 因此,使用复杂类的单身人士最终取决于我们不会混淆他们。

因此,我们可以得到相同的效果,并使用更简单的东西,如variables或模块。 尽pipe如此,如果我们想要使用类来清晰起见,并且因为在Python中一个类是一个对象 ,所以我们已经有了这个对象(不是和实例,但它会像这样)。

 class Singleton: def __new__(cls): raise AssertionError # Singletons can't have instances 

如果我们尝试创build一个实例,那么我们有一个很好的断言错误,并且我们可以存储派生静态成员并在运行时对其进行更改(我爱Python)。 这个对象和其他兄弟一样好(如果你愿意的话,你仍然可以创build它们),但是由于简单起见,它往往会跑得更快。

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

如果您不希望上述基于元类的解决scheme,并且您不喜欢简单的基于装饰器的简单方法(例如,因为在这种情况下,单例类中的静态方法将不起作用),这种折中方法是有效的:

 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)