我一直在阅读布鲁斯·埃克尔的Thinking in python。目前,我正在阅读模式概念章节。在本章中,Eckel展示了python中Singletons的不同实现。但是我对Alex Martelli的Singleton代码(利用继承,而不是私有的嵌套类)有一个不清楚的理解。
这是我对目前代码的理解:
到目前为止我的困惑:
self.__dict__ = self._shared_state
;或者词典的目的许多人提前感谢!
- 三
*更新:每次 Singleton 对象创建后, _shared_state 中存储了什么?
#: Alex' Martelli's Singleton in Python
class Borg:
_shared_state = {}
def __init__(self):
self.__dict__ = self._shared_state
class Singleton(Borg):
def __init__(self, arg):
Borg.__init__(self)
self.val = arg
def __str__(self): return self.val
x = Singleton('sausage')
print x
y = Singleton('eggs')
print y
z = Singleton('spam')
print z
print x
print y
print ´x´
print ´y´
print ´z´
output = '''
sausage
eggs
spam
spam
spam
<__main__.Singleton instance at 0079EF2C>
<__main__.Singleton instance at 0079E10C>
<__main__.Singleton instance at 00798F9C>
'''
答案 0 :(得分:10)
到目前为止答案很好,但我也要直接回答...... self.__dict__
保存实例self
的属性(即状态)(除非它的类具有特殊的东西,如定义{{} 1}} ;-)。因此,通过确保所有实例具有相同的__slots__
,我们确保它们都具有相同的属性,即完全相同的状态。因此,Borg是一般Monostate模式的巧妙Python实现,但没有Robert Martin在他的essay中在Monostate 中用C ++ 确定的任何缺点。
另请参阅Monostate与Singleton的this SO thread - 当然,大多数讨论都与Python无关(显然在Python中,Borg并不妨碍继承,相反!)但是Singleton可以由于例如__dict__
而非常透明,所以权衡是完全不同的......)。
最有趣的事情是什么?自从我第一次构思Borg以来的8年多(在现任Mozilla Messaging首席执行官大卫·阿舍尔之前,提出了酷博格的名字)我有机会使用任何类型的单身人士或单身人士,可能共四次 - 以及三次在这四个中我很快就重新构建了它以支持更灵活的方法! - )(第四次是一个子系统,它没有证明非常成功,也没有得到太多的后续工作/维护; - )。
第二个最有趣的事情是,Guido,个人而言,讨厌 Borg ;-)。并不是说他对Singleton有任何真正的喜欢:他认为在Python中“单一性”,如果需要,应该作为一个模块完成(或者,我想补充一下,伪装成模块的类实例 - 参见例如我的在果壳的第7.2.6节中观察,例如在this海盗副本中;-)。但是,博格似乎特别冒犯了他的设计美学! - )奇怪,因为他确实根据我的Five Easy Pieces文章提名我的PSF会员资格,这基本上都是关于博格(及其变体和考虑因素)的所有内容。 ! - )。好吧,猜猜他可以“讨厌罪恶但爱罪人”,嗯? - )
答案 1 :(得分:6)
class Borg:
_shared_state = {}
def __init__(self):
self.__dict__ = self._shared_state
1)因为Borg._shared_state
在类级别(而不是__init__
)初始化,所以它实际上是静态的,例如由所有类实例共享。
2)self.__dict__
是所有对象都有的字典;它包含所有实例属性。因此,
self.a=1
assert(self.a == self.__dict__['a']) #True
3)请注意,Borg表示“所有实例共享相同的状态”,单例表示“只有一个实例”。这几乎是同样的效果。 Alex Martelli指出Borg是一个pythonic Monostate,所以请看Monostate vs Singleton on SO。
似乎他的Singleton类更恰当地命名为
class ThisClassHasSingletonBehavior(Borg):
....
,因为
<__main__.Singleton instance at 0079EF2C>
<__main__.Singleton instance at 0079E10C>
<__main__.Singleton instance at 00798F9C>
证明x,y,z不是同一个实例,即使它们共享相同的状态。所以它不是单身,它只是具有相同的整体效果,而且很容易。 AFAICT Borg是一个优雅的python模式,用于共享状态(相同状态)行为,其中Singleton是一个优雅的cpp模式。并不是说这种行为是优雅的。
答案 2 :(得分:2)
与普通班级的实例相比,可以帮助您了解他们正在做的事情:
>>> class NormalClass:
def __init__(self, arg):
self.x = arg
>>> a = NormalClass(1)
>>> b = NormalClass(2)
>>> a.x
1
>>> a.__dict__
{'x': 1}
>>> b.x
2
>>> b.__dict__
{'x': 2}
Note how the instances here each have their own unshared __dict__ where
their own x attribute is stored.
编辑添加:现在,让我们让这些普通对象共享一个字典,看看会发生什么......
>>> Another_Dictionary_We_Make = {}
>>> Another_Dictionary_We_Make['x'] = 1000
>>> Another_Dictionary_We_Make
{'x': 1000}
>>> a.__dict__ = Another_Dictionary_We_Make
>>> a.x
1000
>>> b.x
2
>>> b.__dict__ = Another_Dictionary_We_Make
>>> b.x
1000
>>> b.x = 777
>>> b.__dict__
{'x': 777}
>>> a.x
777
>>> a.__dict__
{'x': 777}
这表明在创建两个对象后, dict 是相同的。 Borg / Singleton只是通过初始化实例来共享相同的字典,以便在创建它们时使用相同的 dict 。
答案 3 :(得分:0)
我认为问题是:Borg._shared_state
如何更新?答案:在每个实例中都通过self.__dict__
。
通过self.__dict__ = self._shared_state
,您可以访问每个实例的Borg._shared_state
到self.__dict__
。当您更改实例属性时,您更改了该实例的__dict__
,并且由于该实例的__dict__
指向Borg._shared_state
,您实际上也会更改Borg._shared_state
。
在python中,当您说var1 = var2
时,var1
指向var2
的值,并且它可以访问该值。这就是为什么var1 = a_different_value
实际上会更改var2
的值以及var1
的值的原因。
我也正在阅读上述书籍(通过BitBucket在线)。比特巴克说,几年前开发停止了。我不知道这是为什么。也许作者可以对此发表评论。感谢Alex Martelli这本伟大的书。