在Python中似乎有很多方法来定义单例对象。对Stack Overflow是否有一致的意见?
当前回答
正如公认的答案所说,最常用的方法是只使用一个模块。
考虑到这一点,下面是一个概念的证明:
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)。 单例在定义时初始化,而不是在第一次使用时初始化。 这只是一个简单的例子。我从未在产品代码中实际使用过它,也不打算这样做。
其他回答
好吧,我知道,单胞胎可能是好的,也可能是坏的。这是我的实现,我只是扩展了一个经典的方法,在里面引入一个缓存,并产生许多不同类型的实例,或者许多相同类型的实例,但具有不同的参数。
我称它为Singleton_group,因为它将相似的实例分组在一起,并防止创建具有相同参数的相同类的对象:
# 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>}
每个对象都携带单例缓存…这可能是邪恶的,但对一些人来说很有用:)
我认为强制一个类或实例为单例是多余的。就我个人而言,我喜欢定义一个普通的可实例化类、一个半私有引用和一个简单的工厂函数。
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()
通过这种方式,您可以针对新的实例编写测试,而不会产生副作用,并且不需要在模块中添加全局语句,如果需要,您可以在将来派生变体。
我对此非常不确定,但我的项目使用'惯例单例'(不是强制单例),也就是说,如果我有一个名为DataController的类,我在同一个模块中定义这个:
_data_controller = None
def GetDataController():
global _data_controller
if _data_controller is None:
_data_controller = DataController()
return _data_controller
它并不优雅,因为它足足有六行。但是我所有的单例都使用这个模式,而且它至少是非常显式的(这是python的)。
如果你想继续装饰(注释)类,创建一个单例装饰器(又名注释)是一种优雅的方式。然后将@singleton放在类定义之前。
def singleton(cls):
instances = {}
def getinstance():
if cls not in instances:
instances[cls] = cls()
return instances[cls]
return getinstance
@singleton
class MyClass:
...
谷歌Testing博客上也有一些有趣的文章,讨论了为什么单例是/可能是不好的,并且是一种反模式:
单身人士是病态的说谎者 单身人士都去哪儿了? 单身的根本原因
推荐文章
- 证书验证失败:无法获得本地颁发者证书
- 当使用pip3安装包时,“Python中的ssl模块不可用”
- 无法切换Python与pyenv
- Python if not == vs if !=
- 如何从scikit-learn决策树中提取决策规则?
- 为什么在Mac OS X v10.9 (Mavericks)的终端中apt-get功能不起作用?
- 将旋转的xtick标签与各自的xtick对齐
- 为什么元组可以包含可变项?
- 如何合并字典的字典?
- 如何创建类属性?
- 不区分大小写的“in”
- 在Python中获取迭代器中的元素个数
- 解析日期字符串并更改格式
- 使用try和。Python中的if
- 如何在Python中获得所有直接子目录