为什么Python-Borg/Singleton模式可以工作

为什么Python-Borg/Singleton模式可以工作,python,singleton,Python,Singleton,我只是在网上无意中发现了这些有趣的代码: 我理解什么是单身,但我不理解被剪掉的特定代码。 你能解释一下“\uuuu共享\u状态”到底是如何/在哪里改变的吗 我在ipython试过: In [1]: class Borg: ...: __shared_state = {} ...: def __init__(self): ...: self.__dict__ = self.__shared_state ...: #

我只是在网上无意中发现了这些有趣的代码:

我理解什么是单身,但我不理解被剪掉的特定代码。 你能解释一下“\uuuu共享\u状态”到底是如何/在哪里改变的吗

我在ipython试过:

In [1]: class Borg:
   ...:         __shared_state = {}
   ...:     def __init__(self):
   ...:             self.__dict__ = self.__shared_state
   ...:     # and whatever else you want in your class -- that's all!
   ...: 
In [2]: b1 = Borg()
In [3]: b2 = Borg()
In [4]: b1.foo="123"
In [5]: b2.foo
Out[5]: '123'
In [6]: 
但无法完全理解这是如何发生的。

因为类的实例的
\uuuuuu dict\uuuu
设置为等于
\uuu share\u state
dict。它们指向同一个对象。(
Classname.\uuu dict\uuu
保存所有类属性)

当您这样做时:

b1.foo = "123"

您正在修改
dict
,它是
b1.\uuuu dict\uuuu
Borg.\uuuu共享\u状态
引用的。

实例化任何对象后调用的
\uu init\uuuuu
方法将新创建的对象的
\uu dict\uuu
属性替换为类属性
\uu共享\u状态

a.、
b.、
b.、
Borg.\u Borg\u共享\u状态
都是同一个对象。注意,当从类外部访问private属性时,我们必须添加隐式前缀
\u Borg

In [89]: a.__dict__ is b.__dict__ is Borg._Borg__shared_state
Out[89]: True

这些实例是独立的对象,但通过将它们的
\uuuu dict\uuuu
属性设置为相同的值,这些实例具有相同的属性字典。Python使用属性字典来存储对象上的所有属性,因此实际上这两个实例的行为方式是相同的,因为对它们的属性所做的每一次更改都是对共享属性字典进行的


但是,如果使用
is
来测试相等(浅相等),对象仍然会比较不相等,因为它们仍然是不同的实例(很像单独的博格无人机,它们分享自己的想法,但物理上是不同的)。

顺便问一句,有人能解释一下为什么要使用这样的模式吗?我认为在大多数情况下(在我能想到的每种情况下),你只会持有对同一个实例的多个引用,而没有所有这些黑客行为。它很短,它做了我想要的,我一开始不理解它。现在我明白了,当我等于一个dic时,我只复制一个引用,这对我来说并不清楚。谢谢你的课@大卫·克劳索斯:没问题。对我来说没有什么判断,我只是真的很好奇你会用这种模式做什么。@DavidosKrausos:事实上,现在我明白了。答案在中。不是类的
\uuuu dict\uuuu
而是实例的
\uuuu dict\uuuu
设置为等于
\uu共享状态的
\uu dict>。此版本不适用于新样式的类——请参阅以进行讨论。此外,它的样式不好,因为
id(b1)
将不同于
id(b2)
,而
b1是b2
将给出
False
。处理新旧样式类的一种简单而可靠的方法是声明一个普通类
Foo
,然后在类定义之后执行
Foo=Foo()
In [89]: a.__dict__ is b.__dict__ is Borg._Borg__shared_state
Out[89]: True