python3的可变属性是共享的吗?

olhwl3o2  于 2023-03-09  发布在  Python
关注(0)|答案(1)|浏览(144)

在代码中我示例化了同一个类的两个不同的对象,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'}
oalqel3c

oalqel3c1#

您已经在类级别上定义了mutableimmutable,因此它们在Class的所有示例中都将是shared。链接问题中的答案详细解释了如何避免您所观察到的共享行为,因此我将只解释您的代码中发生了什么。
原则上,这种共享与属性是可变的还是不可变的无关,但是代码中存在一些细微差别,这可能会使它变得混乱。
对于mutable,观察到的行为很容易解释。
首先,dict mutable在内存中始终是同一个对象:

>>> o1, o2 = Class(), Class()                                                                         
>>> o1.mutable is o2.mutable is Class.mutable                                                         
True

当您以任何方式改变mutable时,这个改变将在任何引用该dict的地方出现。

>>> Class.mutable                                                                                     
{}
>>> o2.mutable[1] = 2                                                                                 
>>> o1.change()                                                                                       
>>> Class.mutable                                                                                     
{1: 2, 'key': 'value'}

到目前为止,所有这些都是意料之中的,immutable的棘手之处在于,你没有在change中改变Class.immutable,而是将属性immutableassign 给正在被调用的示例(selfchange
在调用change之前,immutable只存在于类级别上,并且当在示例o1o2上查找时,可以通过类访问immutable(注意o1o2的示例字典是如何为空的)。

>>> 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

在类级别设置的可变对象和不可变对象是以完全相同的方式共享的,理解这一点很重要。唯一的区别是可变对象没有改变它们的方法。但是如果你在change中执行self.mutable = {'key': 'value'},然后在特定示例上调用change,在示例上定义的mutable属性在经由点标记法在示例上查找它时将优先于在类级别上定义的属性。

相关问题