在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))
其他回答
在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
你可以像这样重写__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中没有办法创建私有类或私有构造函数,所以你不能防止多个实例化,只能通过使用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>}
每个对象都携带单例缓存…这可能是邪恶的,但对一些人来说很有用:)
推荐文章
- Django:“projects”vs“apps”
- 如何列出导入的模块?
- 转换Python程序到C/ c++代码?
- 如何从gmtime()的时间+日期输出中获得自epoch以来的秒数?
- 在python模块文档字符串中放入什么?
- 我如何在Django中过滤一个DateTimeField的日期?
- 在Python中用索引迭代列表
- -e,——editable选项在pip install中什么时候有用?
- 使用pip命令从requirements.txt升级python包
- Django更改默认的runserver端口
- 输入对象的datetime。Datetime没有Datetime属性
- numpy数组的Python内存使用情况
- NumPy或Pandas:保持数组类型为整数,同时具有NaN值
- 列表理解条件中的' elif '
- Python的“property”和“attribute”有什么区别?