【问题标题】:Why is this Python Borg / Singleton pattern working为什么这个 Python Borg / Singleton 模式有效
【发布时间】:2012-08-21 02:40:25
【问题描述】:

我只是在网上偶然发现这些有趣的代码被剪掉了:

http://code.activestate.com/recipes/66531/

class Borg:
    __shared_state = {}
    def __init__(self):
        self.__dict__ = self.__shared_state
    # and whatever else you want in your class -- that's all!

我明白什么是单例,但我不明白特定的代码被剪断了。 你能解释一下“__shared_state”是如何/在哪里改变的吗?

我在 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]: 

但无法完全理解这是如何发生的。

【问题讨论】:

  • 此版本不适用于新式类——请参阅stackoverflow.com/questions/8992241/… 进行讨论。
  • 另外,这是一种不好的风格,因为id(b1) 将不同于id(b2),而b1 is b2 将给出False。一种适用于新旧样式类的简单而可靠的方法是声明一个普通类Foo,然后在类定义之后立即执行Foo = Foo()

标签: python singleton


【解决方案1】:

因为 类的 实例的 __dict__ 设置为等于 __share_state 字典。它们指向相同的对象。 (Classname.__dict__ 包含所有类属性)

当你这样做时:

b1.foo = "123"

您正在修改b1.__dict__Borg.__shared_state 引用的dict

【讨论】:

  • 顺便说一下,谁能解释一下为什么你会想要使用这样的模式?我认为在大多数情况下(在我能想到的每一种情况下),您只需持有对 same 实例的多个引用,而无需所有这些骇客。
  • 它很短,它做我想做的事,一开始我不明白。现在我明白了,当我等于一个 dic 时,我只复制一个引用,这对我来说并不清楚。感谢您的课程!
  • @DavidosKrausos:没问题。我没有判断力,我只是真的很好奇你会用这种模式做什么。
  • @DavidosKrausos:实际上,现在我明白了。答案在this Question
  • 不是类的__dict__,而是实例的__dict__,它们设置为等于__shared_state dict。
【解决方案2】:

__init__方法,在实例化任何对象后调用,将新创建对象的__dict__属性替换为类属性__shared_state

a.__dict__b.__dict__Borg._Borg__shared_state 都是同一个对象。请注意,当从类外部访问私有属性时,我们必须添加隐式前缀_Borg

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

【讨论】:

    【解决方案3】:

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

    但是,如果使用is 来测试相等性(浅相等性),对象仍然会比较不相等,因为它们仍然是不同的实例(很像单个 Borg 无人机,它们共享思想但在物理上是不同的)。

    【讨论】:

      猜你喜欢
      • 2010-11-22
      • 1970-01-01
      • 2012-01-05
      • 2013-08-14
      • 1970-01-01
      • 1970-01-01
      • 2010-11-06
      • 1970-01-01
      相关资源
      最近更新 更多