在Python中似乎有很多方法来定义单例对象。对Stack Overflow是否有一致的意见?
当前回答
辛格尔顿同父异母的兄弟
我完全同意staale的观点,我在这里留下了一个创建单胎同父异母兄弟的例子:
class void:pass
a = void();
a.__class__ = Singleton
即使看起来不像单例,A现在也会报告为与单例属于同一个类。因此,使用复杂类的单例最终依赖于我们没有过多地干扰它们。
因此,我们可以使用更简单的东西,如变量或模块,以达到同样的效果。尽管如此,如果我们想要使用类来明确,并且因为在Python中类是一个对象,所以我们已经有了对象(不是实例,但它会像)。
class Singleton:
def __new__(cls): raise AssertionError # Singletons can't have instances
如果我们尝试创建一个实例,我们会有一个很好的断言错误,我们可以在派生上存储静态成员,并在运行时对它们进行更改(我喜欢Python)。这个对象和其他同父异母的兄弟一样好(如果你愿意,你仍然可以创建它们),但是由于简单,它往往会运行得更快。
其他回答
作为Python的新手,我不确定最常见的习语是什么,但我能想到的最简单的事情就是使用模块而不是类。类中的实例方法变成了模块中的函数,任何数据都变成了模块中的变量,而不是类的成员。我怀疑这是解决人们使用单例对象的问题的python方法。
如果你真的想要一个单例类,有一个合理的实现描述在谷歌的第一个点击“Python singleton”,具体地说:
class Singleton:
__single = None
def __init__( self ):
if Singleton.__single:
raise Singleton.__single
Singleton.__single = self
这似乎奏效了。
我的简单解决方案是基于函数参数的默认值。
def getSystemContext(contextObjList=[]):
if len( contextObjList ) == 0:
contextObjList.append( Context() )
pass
return contextObjList[0]
class Context(object):
# Anything you want here
我真的不认为有这个需要,因为一个带有函数(而不是类)的模块可以很好地作为一个单例。它的所有变量都将绑定到模块,无论如何都不能重复实例化。
如果你确实希望使用一个类,在Python中没有办法创建私有类或私有构造函数,所以你不能防止多个实例化,只能通过使用API中的约定。我仍然会将方法放在模块中,并将模块视为单例模块。
好吧,我知道,单胞胎可能是好的,也可能是坏的。这是我的实现,我只是扩展了一个经典的方法,在里面引入一个缓存,并产生许多不同类型的实例,或者许多相同类型的实例,但具有不同的参数。
我称它为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>}
每个对象都携带单例缓存…这可能是邪恶的,但对一些人来说很有用:)
我对此非常不确定,但我的项目使用'惯例单例'(不是强制单例),也就是说,如果我有一个名为DataController的类,我在同一个模块中定义这个:
_data_controller = None
def GetDataController():
global _data_controller
if _data_controller is None:
_data_controller = DataController()
return _data_controller
它并不优雅,因为它足足有六行。但是我所有的单例都使用这个模式,而且它至少是非常显式的(这是python的)。
推荐文章
- Numpy Max vs amax vs maximum
- 我应该在.gitignore文件中添加Django迁移文件吗?
- 每n行有熊猫
- 实例属性attribute_name定义在__init__之外
- 如何获取在Python中捕获的异常的名称?
- 第一次出现的值大于现有值的Numpy
- 如何从Python函数中返回两个值?
- 前一个月的Python日期
- Python中方括号括起来的列表和圆括号括起来的列表有什么区别?
- Python日志记录不输出任何东西
- 每n秒运行特定代码
- SQLAlchemy是否有与Django的get_or_create等价的函数?
- 如何将python datetime转换为字符串,具有可读格式的日期?
- 美丽的汤和提取div及其内容的ID
- 在Python中重置生成器对象