python如何向类添加属性val1和val2。python是否在内部调用类似b1的东西。u共享_状态['val1']='Jaga Gola!!!'
# Borg (monostate pattern) lets a class have as many instances as one likes,
# but ensures that they all share the same state
class Borg:
__shared_state = {}
def __init__(self):
self.__dict__ = self.__shared_state
b1 = Borg()
b2 = Borg()
print(b1 == b2)
b1.val1 = 'Jaga Gola!!!'
b1.val2 = 'BOOOM!!!'
print(b2.val1, b1.val2)
为什么如果我删除了_shared_state and self.__dict__ = self.__shared_state
,我就不能向类添加属性并得到错误:AttributeError:'Borg'对象没有属性'val1'
class Borg:
def __init__(self):
pass
b1 = Borg()
b2 = Borg()
print(b1 == b2)
b1.val1 = 'Jaga Gola!!!'
b1.val2 = 'BOOOM!!!'
print(b2.val1, b1.val2)
你在那里做的事情很有趣,它基于可变性:
声明的初始
__shared_state
是在执行任何代码之前创建的。该字典称为Class属性,因为它链接到类,而不是实例(不使用self
进行声明)。这意味着__shared_state
在b1
和b2
之间共享,因为它是在它们之前创建的,并且因为它是一个dict
,所以它是可变的什么是可变的
这意味着分配给两个不同实例的一个字典将引用相同的内存地址,即使我们更改了听写,内存地址也将保持不变。这是一个探针:
注意到他们是如何拥有相同的id的吗?这是因为它们引用的是同一个对象,而且
dictionary
类型是可变的,在一个对象中更改字典意味着您正在更改这两个对象的字典,因为它们是相同的:这不会发生在不可变的整数上:
当你删除你的
__shared_state
时,当你分配b1.val1 = 'Jaga Gola!!!'
和b1.val2 = 'BOOOM!!!'
时,它只是从b1
分配给字典,这就是为什么当你试图打印b2.val1
和b2.val2
时会出现错误在此代码中:
__shared_state = {}
行出现在类级别,因此它只添加一次到类Borg
,而不是添加到类型为Borg
的每个单独对象。这与之后写Borg.__shared_state = {}
是一样的李>self.__dict__ = self.__shared_state
令人困惑,因为它使用了self.
两次,但效果非常不同:self.something
时,在对象self
中设置该something
。这并不奇怪李>self.something
读取时,首先在self
对象中查找something
,如果在那里找不到,则在对象的类中查找。这种想法听起来很奇怪,但实际上你一直在使用它:这就是方法通常的工作方式。例如,在s = "foo"; b = s.startswith("f")
中,对象s
没有属性startswith
,但是它的类str
有属性,这就是调用该方法时使用的李>这一行:
最终转化为:
但是我们知道
b1.__dict__
等于Borg.__shared_state
,所以它被分配给它。然后:翻译为:
我们再次知道},因此
b2.__dict__
等于相同的{val1
被发现如果您在开始时删除了关于
__shared_state
的内容,那么b1
和b2
将获得它们自己的__dict__
对象,因此将val1
放入b1
的dict中对b2
没有影响,这就是您所提到的错误的原因这对于理解正在发生的事情来说是很好的,但是您应该意识到这段代码并不能保证工作,并且可能会在Python的未来版本或其他实现(如PyPy)中崩溃。Python documentation for ^{} 将其描述为“只读属性”,因此根本不应该为其赋值。不要在其他人可能运行的代码中执行此操作
事实上,认为
a.foo
就是a.__dict__['foo']
的想法是一个巨大的简化。首先,我们已经遇到了这样的情况:有时在阅读时,它后面跟着a.__class__.__dict__['foo']
。另一个例子是a.__dict__
显然不是a.__dict__['__dict__']
,否则它将如何结束!?这个过程有些复杂,在the Data Model docs中有记录获得此行为的支持方式是使用特殊的
__setattr__
和__getattr__
方法(也在这些数据模型文档中描述),如下所示:相关问题 更多 >
编程相关推荐