python3 可变属性是否共享?
are python3 mutable attributes shared?
在代码中我实例化了相同 class 的两个不同对象,object1
怎么可能改变 object2
的属性?如何保留不同的 "self.mutable" 变量?我的错误在哪里? :-)
谢谢
class Class:
mutable = {}
immutable = 0
def change(self):
self.immutable = 1
self.mutable["key"] = "value"
def observe(self):
print(self.immutable, self.mutable)
object1, object2 = Class(), Class()
object1.change()
object2.observe()
# output is: 0 {'key': 'value'}
您已在 class 级别定义了 mutable
和 immutable
,
因此,在 Class
的所有实例中,两者都将是 shared。链接问题中的答案详细解释了如何避免您观察到的共享行为,因此我将只解释您的代码发生了什么。
原则上,此共享与可变或不可变属性无关,但您的代码中存在一些细微差别,可能会造成混淆。
在 mutable
的情况下,观察到的行为很容易解释。
首先,字典mutable
在内存中总是同一个对象:
>>> o1, o2 = Class(), Class()
>>> o1.mutable is o2.mutable is Class.mutable
True
当您 mutate
以任何方式可变时,此更改将随处可见,引用该字典。
>>> Class.mutable
{}
>>> o2.mutable[1] = 2
>>> o1.change()
>>> Class.mutable
{1: 2, 'key': 'value'}
到目前为止,所有这一切都在意料之中。 immutable
的棘手部分是你不改变 Class.mutable
,你 分配 属性 mutable
到实例(self
) change
正在通话中!
在调用 change 之前,immutable
仅存在于 class 级别,并且在实例 o1
或 [=27= 上查找时通过 class 访问]. (注意 o1
和 o2
的实例字典是空的。)
>>> o1, o2 = Class(), Class()
>>> o1.immutable, o2.immutable, Class.immutable
(0, 0, 0)
>>> o1.__dict__, o2.__dict__, 'immutable' in Class.__dict__
({}, {}, True)
在 o2
上调用 change
时,您只在实例 o2
!
上设置属性 immutable = 1
>>> o2.change()
>>> o1.immutable, o2.immutable, Class.immutable
(0, 1, 0)
>>> o1.__dict__, o2.__dict__, 'immutable' in Class.__dict__
({}, {'immutable': 1}, True)
>>> o1.immutable is Class.immutable
True
>>> o2.immutable is Class.immutable
False
了解在 class 级别设置的可变和不可变对象以完全相同的方式共享很重要。唯一的区别是可变对象没有改变它们的方法。但是,如果您在 change
中完成了 self.mutable = {'key': 'value'}
,然后在特定实例上调用了 change
,则实例上定义的 mutable
属性将优先于 class 通过点符号在实例上查找时的级别。
在代码中我实例化了相同 class 的两个不同对象,object1
怎么可能改变 object2
的属性?如何保留不同的 "self.mutable" 变量?我的错误在哪里? :-)
谢谢
class Class:
mutable = {}
immutable = 0
def change(self):
self.immutable = 1
self.mutable["key"] = "value"
def observe(self):
print(self.immutable, self.mutable)
object1, object2 = Class(), Class()
object1.change()
object2.observe()
# output is: 0 {'key': 'value'}
您已在 class 级别定义了 mutable
和 immutable
,
因此,在 Class
的所有实例中,两者都将是 shared。链接问题中的答案详细解释了如何避免您观察到的共享行为,因此我将只解释您的代码发生了什么。
原则上,此共享与可变或不可变属性无关,但您的代码中存在一些细微差别,可能会造成混淆。
在 mutable
的情况下,观察到的行为很容易解释。
首先,字典mutable
在内存中总是同一个对象:
>>> o1, o2 = Class(), Class()
>>> o1.mutable is o2.mutable is Class.mutable
True
当您 mutate
以任何方式可变时,此更改将随处可见,引用该字典。
>>> Class.mutable
{}
>>> o2.mutable[1] = 2
>>> o1.change()
>>> Class.mutable
{1: 2, 'key': 'value'}
到目前为止,所有这一切都在意料之中。 immutable
的棘手部分是你不改变 Class.mutable
,你 分配 属性 mutable
到实例(self
) change
正在通话中!
在调用 change 之前,immutable
仅存在于 class 级别,并且在实例 o1
或 [=27= 上查找时通过 class 访问]. (注意 o1
和 o2
的实例字典是空的。)
>>> o1, o2 = Class(), Class()
>>> o1.immutable, o2.immutable, Class.immutable
(0, 0, 0)
>>> o1.__dict__, o2.__dict__, 'immutable' in Class.__dict__
({}, {}, True)
在 o2
上调用 change
时,您只在实例 o2
!
immutable = 1
>>> o2.change()
>>> o1.immutable, o2.immutable, Class.immutable
(0, 1, 0)
>>> o1.__dict__, o2.__dict__, 'immutable' in Class.__dict__
({}, {'immutable': 1}, True)
>>> o1.immutable is Class.immutable
True
>>> o2.immutable is Class.immutable
False
了解在 class 级别设置的可变和不可变对象以完全相同的方式共享很重要。唯一的区别是可变对象没有改变它们的方法。但是,如果您在 change
中完成了 self.mutable = {'key': 'value'}
,然后在特定实例上调用了 change
,则实例上定义的 mutable
属性将优先于 class 通过点符号在实例上查找时的级别。