繁体   English   中英

Python: __dict__ shows class attribute for the object of the class even when the behavior inside the __init__ mutates the class attribute

[英]Python: __dict__ shows class attribute for the object of the class even when the behavior inside the __init__ mutates the class attribute

据我了解,

对于像列表这样的可变 object,如果底层 object 支持类似列表的突变,+=(增强分配)会导致 object 的突变。 当然,这不适用于不支持突变的不可变对象,因为__iadd__不存在,而__add__是被调用的对象。

考虑以下代码:

class TestClass:
    bar = []

    def __init__(self, x):
        self.bar += [x]


f = TestClass(1)
g = TestClass(2)
h = TestClass(3)
print(f.bar)
print(g.bar)
print(TestClass.bar)

现在,我明白为什么所有三个 g,f,h 都会打印出[1, 2, 3]因为我们正在“改变” class 属性。

但是当我尝试通过print(f.__dict__)查看对象的命名空间时,我也看到了 object 中的 bar 属性。

问题 1:如果实际发生突变的属性是 class 属性,为什么会在 object 命名空间中创建实例?

其次,“如果”该实例变量在对象中创建(如 f),那么f.bar += 4应该只影响 object f,因为 f 中的新实例变量 bar 应该遮蔽了 class 属性。 但我看到依次执行f.bar+=4也会更新 class 属性,这让我完全困惑。

有人可以帮我吗?

这可能有点微妙。 你可以想到

self.bar += [x]

相当于

self.bar = self.bar.__iadd__([x])

因此, self.bar.__iadd__([x])改变列表,本质上调用list.extend ,然后返回列表 object 此列表 object 与TestClass.bar引用的相同,已分配给实例属性

所以现在你有一个与 class 属性同名的实例属性,并且两者都绑定到同一个列表 object

这甚至在 [documentation] 中被警告:

对于属性引用的目标, 关于 class 和实例属性的相同警告适用于常规分配。

需要注意的是:

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM